#clojure log - Mar 09 2009

The Joy of Clojure
Main Clojure site
Google Group
List of all logged dates

0:00 durka42: the API page stays with the latest release

0:01 cmvkk: hmm, i'm not quite sure how this would work but it's a promising avenue, thanks.

0:04 durka42: Raynes: re. that quote: i'm not afraid of heights, but i have no idea how to drive a stick

0:04 cmvkk: haha, me too.

0:06 hmm, maybe i could roll my own 'future caching'.

0:06 durka42: how would that work

0:07 cmvkk: well, the closures are called with a number as an argument, which has to increment in the right order. 0, 1, 2, etc.

0:07 so i could wrap each closure around an agent containing the "next N samples", and keep a list of how far ahead the cache is.

0:08 then when the closure gets called with the number that's the end of the cache, I batch calculate another N samples and store them in the cache, in a separate thread.

0:09 Raynes: I hate how Haskell developers make me feel like Clojure and LISP are useless.

0:09 :\

0:09 s/LISP/LISP in general/

0:10 cmvkk: the developers tell you that, or you actually feel that way?

0:10 p_l: Raynes: Clojure just appeared, so most of the time they attitude steems from having few things that CL community haven't

0:10 Raynes: The developers tell me that. It's annoying.

0:11 cmvkk: Dont think I'd be here if I felt that way :p

0:11 p_l: they feel full of themselves because they managed to create a strong community with constant growth. Still, nothing killed Lisp for 50 years...

0:11 Raynes: "Haskell is better." is what I hear twice a week. :\

0:12 replaca: not even the lispers :), though they sure tried

0:12 Raynes: I can't help but shake the feeling that Haskell can only go downhill from where it's at.

0:12 It's no doubt that developers these days just don't like pure functional programming.

0:12 p_l: Raynes: functional languages (and in fact, all non "mainstream" languages) are on uphill now

0:23 zakwilson: There are languages for feeling smug, and languages for getting crap done. Clojure is a language for getting crap done.

0:24 Haskell can be useful, and CL is quite nice, sometimes, but Clojure can certainly hold its own when it comes to solving whatever ugly, real-world problem you have.

0:25 p_l: I would say that clojure has simply a big advantage of being JVM hosted :)

0:29 zakwilson: The JVM is part of its advantage, but the language itself is designed around getting stuff done.

0:29 timmcd: I've got a question; is there a built-in function for adding onto an end of a list?

0:31 p_l: zakwilson: experienced Haskell, CL or Clojure programmer probably would spend similar time. I had seen someone write his own DHCP proxy in Haskell in short time because nothing worked for his network :)

0:33 timmcd: So no, there isn't? If not, I'll just make one of my own. Can't be that hard

0:33 durka42: there's concat but it needs a list

0:33 vectors grow at the end with conj

0:34 hiredman: timmcd: you should not add to the end of a list

0:34 that is not something the design of linkedlists allows for well

0:35 timmcd: hiredman, mmk. How would you suggest making an ascending-order function that takes a list and rearranges it into ascending order?

0:35 Raynes: Use teh vector

0:36 hiredman: ,(sort '(3 2 8 5 3))

0:36 clojurebot: (2 3 3 5 8)

0:36 hiredman: ~def sort

0:37 timmcd: That is a nifty bot...

0:38 But how would I go about doing it myself? As a learning project?

0:38 Like, I know there is a (. '(1 2 3) size) function

0:38 but I still made this:

0:38 (defn give-me-length [num x] "Helper for calculatin list-length."

0:38 grr

0:38 meh

0:38 Well, I made my on length function for lists

0:39 hiredman: ...

0:39 arbscht: ,(count '(1 2 3))

0:39 clojurebot: 3

0:39 timmcd: ...

0:39 >:P

0:39 ,(count '[1 2 3])

0:39 clojurebot: 3

0:39 timmcd: meh

0:39 You people hate me >_>

0:40 hiredman: timmcd: are you planning to do a bubble sort or what?

0:40 timmcd: timmcd, bubble...sort?

0:40 timmcd, I'm fairly new to functional programming, and new to Clojure all together

0:40 *hiredman

0:40 arbscht: bubble sort is a general sorting algorithm

0:41 it isn't unique to functional programming

0:41 replaca: timmcd: the usual way for accumulating lists (in all lisps) is to build them backwards and then reverse them when you have what you want

0:42 timmcd: replaca: Mmk. Thanks

0:42 hiredman: in clojure you can use a vector

0:42 timmcd: That I can

0:42 replaca: timmcd: in clojure you tend to use a vector instead cause vectors have fast append, and then you can use (list v) to turn in into a list at the end

0:42 hiredman: and leave out the reversing

0:42 uh

0:42 timmcd: Is there any reason why you would use a list instead of a vector?

0:42 replaca: if you really need a list

0:42 hiredman: (seq v) not (list v)

0:42 ,(list [1])

0:42 clojurebot: ([1])

0:42 hiredman: not what you want

0:43 timmcd: Yeah

0:43 replaca: hiredman: sorry, you're right

0:43 timmcd: ,(seq v)

0:43 clojurebot: java.lang.Exception: Unable to resolve symbol: v in this context

0:43 timmcd: Is there any reason why you would use a list instead of a vector?

0:44 replaca: timmcd: when you want to jam a lot of stuff on the front, lists might be faster, but usually, no

0:44 timmcd: Ok

0:44 THanks

0:44 replaca: one nice thing about lists is that have multiple versions of them all pointing and different subparts is very efficient

0:44 hiredman: if you don't need O(n) access to the middle of the list

0:45 replaca: hiredman: you mean O(1)

0:45 hiredman: I do

0:45 arbscht: you would use lists to represent clojure code

0:45 replaca: that, too!

0:46 timmcd: also, is there a method for removing an item from a vector? Ie: (drop '[1 2 3] 1) -> [2 3]?

0:46 arbscht: Interesting. Lets say I had a bit of code that calls a variable piece of code that can be changed. Would you store that var. piece of code as a method, or as a list?

0:47 replaca: sort of: (drop 1 [1 2 3])

0:47 hiredman: replaca: that doesn't remove from the vector

0:47 replaca: note, no quote for literal vectors (or maps)

0:47 timmcd: and calls this var. code every once inawhile (So its not just once right away)

0:47 hiredman: datastruictures in clojure are immutable

0:47 and drop works on seqs

0:47 not vectors

0:48 ,(doc subvec)

0:48 clojurebot: "([v start] [v start end]); Returns a persistent vector of the items in vector from start (inclusive) to end (exclusive). If end is not supplied, defaults to (count vector). This operation is O(1) and very fast, as the resulting vector shares structure with the original and no trimming is done."

0:48 timmcd: Seems to work on vectors for me...

0:48 replaca: correct, it returns a seq (a list mapped onto the vector in this case) that represents that drop

0:48 hiredman: timmcd: drop calls seq on the vector

0:48 timmcd: oh yeah it made a seq

0:48 hiredman: ,(seq [1 2 3])

0:48 timmcd: my bade

0:48 clojurebot: (1 2 3)

0:48 timmcd: *bad

0:48 replaca: if you need it to stay a vector, subvec is a better bet

0:48 arbscht: timmcd: sounds like you want a function in that case

0:48 timmcd: ANd drop just removes n amount from the seq

0:49 replaca: yup

0:49 timmcd: Sort of same with subvec

0:49 hiredman: ~def subvec

0:49 replaca: yeah, the argument object always stays the same

0:49 timmcd: Is it possible to remove N from the vector. Like: (rm [1 2 2 3] 2) -> [1 3]?

0:49 hiredman: filter

0:50 timmcd: ,(doc filter)

0:50 clojurebot: "([pred coll]); Returns a lazy sequence of the items in coll for which (pred item) returns true. pred must be free of side-effects."

0:50 hiredman: but, again, it works on seqs

0:50 so you lose the vector

0:50 timmcd: hrm

0:50 Is there a way to convert sequence to vector? I'm guessing now

0:50 *no*

0:50 replaca: you can always add the vector back after the fact with (vector alis)

0:50 hiredman: ,(vec (range 5))

0:50 clojurebot: [0 1 2 3 4]

0:51 replaca: I sorry, vec

0:51 hiredman: ,(vector 1 2 3)

0:51 clojurebot: [1 2 3]

0:51 timmcd: ,(vector '(1 2 3))

0:51 clojurebot: [(1 2 3)]

0:51 cmvkk: on a side note, i don't find that very intuitive

0:52 timmcd: I agree

0:52 Is it possible to run a regexp on a vector?

0:52 hiredman: *shrug*

0:52 No

0:52 replaca: timmcd: what do you mean by that?

0:52 hiredman: a vector is not a string

0:53 Raynes: Looky

0:53 replaca: regexps map to strings, so you could map regexps over strings *in* a vector

0:53 timmcd: replaca: I mean using the same regexp syntax to search through and possibly replace bits in vectors

0:53 Raynes: ,(apply vector '(1 2 3))

0:53 clojurebot: [1 2 3]

0:53 Raynes: :D

0:53 timmcd: *claps for Raynes*

0:53 Raynes: I win.

0:53 timmcd: Lol yup

0:53 replaca: Raynes: that's just cause I was too lazy to type it :-)

0:54 timmcd: >_> sure

0:54 ^_^

0:54 Raynes: replaca: :p

0:54 cmvkk: if you have a vector of characters you can run a regexp on it, if you convert it to a string first...

0:54 Raynes: This is another reason I like Clojure, I've been learning it for a few weeks and I actually stand up against language experts on answering questions. :>

0:54 timmcd: lol

0:55 I'm still shocked that there is no way to remove a specific item from a vector

0:55 replaca: we're all noobs here

0:55 timmcd: I guess you could always just

0:55 iterate through the vector till you find what you want

0:55 and remove it

0:55 cmvkk: you can use subvec but it's a little unweildy

0:55 and filter also

0:55 Raynes: ,(apply str [\a\b\c\d])

0:55 clojurebot: "abcd"

0:56 timmcd: Is there a way to iterate through vector without converting to seq? dovec vrs. doseq?

0:56 durka42: ,(let [v [1 2 3 4]] (concat (subvec v 0 2) (subvec v 3)))

0:56 timmcd: ,(doc dovec)

0:56 clojurebot: (1 2 4)

0:56 timmcd: lol

0:56 clojurebot: java.lang.Exception: Unable to resolve var: dovec in this context

0:56 timmcd: of course

0:56 durka42: why would you need to do that

0:56 Raynes: What's wrong with.

0:57 timmcd: well, to do what you just did

0:57 >_<

0:57 Raynes: ,(remove #(= % "x") ["a" "x"])

0:57 clojurebot: ("a")

0:57 replaca: (remove #(= % 2) [1 2 3 2 4 5 2 3])

0:57 ,(remove #(= % 2) [1 2 3 2 4 5 2 3])

0:57 clojurebot: (1 3 4 5 3)

0:57 Raynes: replaca: Great mind think alike.

0:57 timmcd: o.0

0:57 Raynes: minds*

0:57 replaca: but then you need vec again :-)

0:58 timmcd: ,(remove #(= % :foobar) [1 2 :foobar 3 4 5])

0:58 clojurebot: (1 2 3 4 5)

0:58 timmcd: ah yeah

0:58 ,(apply vector (remove #(= % :foobar) [1 2 :foobar 3 4 5])

0:58 clojurebot: EOF while reading

0:58 Raynes: I win again!!!

0:58 timmcd: EOF?

0:58 replaca: timmcd: I think that most of the time when we're doing first-order things like this, we just use seq, but you have to be careful if you have a conj in there

0:58 * Raynes is on a roll.

0:58 durka42: that's remove by values, but no dice if you just have the index

0:58 Raynes: timmcd: YOu forgot a paren

0:59 Aw.

0:59 hiredman: ,(indexOf [1 2 3 4 5] 3)

0:59 clojurebot: java.lang.Exception: Unable to resolve symbol: indexOf in this context

0:59 hiredman: ,(.indexOf [1 2 3 4 5] 3)

0:59 clojurebot: 2

1:01 hiredman: ,(let [v [1 2 3 4 5] i (.indexOf v 3) f (subvec v 0 i) b (subvec v (inc i) (count v)] (reduce conj f b))

1:01 clojurebot: Unmatched delimiter: ]

1:02 hiredman: ,(let [v [1 2 3 4 5] i (.indexOf v 3) f (subvec v 0 i) b (subvec v (inc i) (count v))] (reduce conj f b))

1:02 clojurebot: [1 2 4 5]

1:02 hiredman: ,(let [v [1 2 3 4 5] i (.indexOf v 3) f (subvec v 0 i) b (drop i v)] (reduce conj f b))

1:02 clojurebot: [1 2 3 4 5]

1:02 hiredman: ,(let [v [1 2 3 4 5] i (.indexOf v 3) f (subvec v 0 i) b (drop (inc i) v)] (reduce conj f b))

1:02 clojurebot: [1 2 4 5]

1:03 durka42: ,(vec (mapcat #(if (not= %2 2) (list %1)) [1 2 2 3] (iterate inc 0)))

1:03 clojurebot: [1 2 3]

1:03 slashus21: ,(let [v [1] split-list (split-at 0 v)] (concat (split-list 0) (next (split-list 1))))

1:03 clojurebot: ()

1:03 slashus21: ,(let [v [1 2 3 4 5 6] split-list (split-at 3 v)] (concat (split-list 0) (next (split-list 1))))

1:03 clojurebot: (1 2 3 5 6)

1:04 replaca: split-at, cool. I always use take/drop. Is split-at faster?

1:04 durka42: split-at uses take/drop

1:05 hmm, it would be cool if vectors could take vectors of integers as arguments

1:05 like in matlab

1:05 hiredman: vec is cheating

1:05 ~vec is cheating

1:05 clojurebot: Ack. Ack.

1:14 slashus21: ,(let [v [1 2 3 4 5 6] split-list (split-at 3 v)] (concat (first split-list) (next (second split-list))))

1:14 clojurebot: (1 2 3 5 6)

1:14 slashus21: prettier way of writing it.

1:22 replaca: ,(let [v [1 2 3 4 5 6] [a b] (split-at 3 v)] (concat a (next b)))

1:22 clojurebot: (1 2 3 5 6)

1:22 replaca: with a destructuring bind, ftw! :-)

1:26 slashus2: replaca: Blasted. You beat me.

1:27 replaca: slashus2: standing on the shoulders of giants, my friend

1:29 slashus2: replaca: I am still climbing.

1:30 replaca: slashus2: yup, that's what makes it fun. It's like Rich has laid out a new territory and we're all exploring

1:30 slashus2: replaca: I tried to beat him in fixing a bug that I discovered today, but I failed.

1:30 Raynes: Exploratory programming.

1:47 hiredman: Could you make clojurebot so that when someone says " clojurebot: can clojure <insert something here>" it will say, "Yes, Clojure can do that!"

1:48 durka42: clojurebot: can clojure is <reply>Yes, Clojure can do that!

1:48 clojurebot: In Ordnung

1:48 durka42: clojurebot: can clojure cure cancer?

1:48 clojurebot: Yes, Clojure can do that!

1:48 cp2: yes

1:48 durka42: clojurebot: can clojure vec?

1:48 clojurebot: Yes, Clojure can do that!

1:48 cp2: git clone git://cdc.org/cures/cancer-clj.git

1:49 ayrnieu: the folly in that plan is that someone could say "clojurebot: can clojure defeat Chuck Norris?", and then both you and clojurebot will be destroyed for blasphemy.

1:49 cp2: er

1:49 not cdc.org

1:49 slashus2: clojurebot: Can clojure defeat Check Norris?

1:49 clojurebot: clojure is cheating

1:50 hiredman: ugh

1:50 durka42: clojurebot: can clojure defeat Chuck Norris? is <reply>That is the one thing Clojure can not do.

1:50 clojurebot: c'est bon!

1:50 durka42: ~can clojure defeat Chuck Norris?

1:50 clojurebot: Yes, Clojure can do that!

1:50 hiredman: still case sensitive

1:50 ayrnieu: I'll miss you, durka.

1:50 hiredman: :(

1:52 Raynes: O.O

1:52 clojurebot: can clojure made the universe implode?

1:52 clojurebot: Yes, Clojure can do that!

1:52 Raynes: Oops :|

1:52 slashus2: It can even do things that make no sense! wee

2:01 ~can clojure give up Christianity for lint?

2:01 clojurebot: Yes, Clojure can do that!

3:11 p_l: someone ported Hakell's FAQ to clojurebot? ;P

3:25 alinp: hi

3:25 which are the implementations of clojure.lang.IFn ?

3:26 cmvkk: http://github.com/Chouser/clojure-classes/raw/master/graph-w-legend.png

3:27 alinp: thanks

3:27 cmvkk: heh, i can't even find IFn on that

3:28 alinp: I found it

3:28 :)

3:28 right under Serializable

3:28 cmvkk: ah yes.

3:29 alinp: so APersistentSet is an implementation of it

3:29 cmvkk: ,(#{:a :b :c} :a)

3:29 alinp: which is an abstract class ...

3:29 clojurebot: :a

3:30 alinp: the thing is that I want to play a bit with clojure classes

3:30 cmvkk: i think that's encouraged

3:30 alinp: try to do a lazy seq right in java ... if is possible

4:04 slashus2: Is there a way to do something like a generator function yet? I am guessing streams will add this functionality?

4:05 cmvkk: what do you mean by that?

4:07 slashus2: I am trying to figure out the best way to implement the genRandom function here http://shootout.alioth.debian.org/gp4/benchmark.php?test=fasta&lang=python&id=2

4:11 cmvkk: well you could do like (def *random* (new java.util.Random))

4:11 then define genRandom so that it calls (.nextInt *random*) or whatever

4:11 and does the calculation and returns it

4:11 oh wait

4:11 that's not how that function works at all.

4:12 :)

4:12 slashus2: It is a generator function, which mutates seed.

4:12 cmvkk: right. you can do it with a lazy seq

4:12 slashus2: That is what I am trying to figure out how to do.

4:13 cmvkk: it's a matter of defining a function with seed as one of the arguments, then doing a recursive call of the function inside the lazy seq.

4:13 rebinding seed when you do that.

4:13 i think anyway...

4:14 hiredman: I thought I saw something about Random not being thread safe

4:14 cmvkk: it's probably not.

4:14 it's some sort of mutable object, so why would it be?

4:15 hiredman: google seems to think it is

4:16 older releases jdk1.4 etc, nay have been unsafe

4:16 may

4:17 cmvkk: ~paste

4:17 clojurebot: lisppaste8, url

4:17 lisppaste8: To use the lisppaste bot, visit http://paste.lisp.org/new/clojure and enter your paste.

4:18 cmvkk pasted "gen-random" at http://paste.lisp.org/display/76687

4:18 cmvkk: that's probably slow, but i think that's how you would do it

4:20 arggh, i hate you "can't await in agent action"! all my plans are ruined forever.

4:22 hiredman: also, send-offs are held till the agent action completes, unless you explicitly release them

4:23 cmvkk: i want agents that send-off to other agents that send-off to other agents. and then wait for them to complete down the line.

4:24 as long as I use send-off, and as long as I don't have agents that await each other, I don't see what the problem is.

4:24 hiredman: *shrug*

4:24 cmvkk: once again, i demonstrate that i don't really understand clojure's concurrency well enough to implement it correctly.

4:24 hiredman: I haven't used agents much

4:25 why are you awaiting?

4:25 cmvkk: well it would be a boon in this case, but i need to add it into what's already a fairly complex system of closures calling closures etc.

4:26 the plan was for each closure to have a 'future cache', where it would precalculate n values, then when it started to get low, it would send-off to precalculate some more values while still providing cached ones to the calling fn.

4:26 but at the very beginning, there aren't any values at all. so we have to await for some of them to get calculated before we can return a value.

4:27 hiredman: ah

4:27 cmvkk: I guess, anyway.

4:27 I suppose I could just have them return nil, then build it in so that if it returns nil, it retries for the value rather than caching it.

4:27 hiredman: I have just used a wonderful hammer, so your problem (of course) seems very much like a nail

4:27 cmvkk: but that seems like it would end up being a waste of cycles.

4:27 hmm, do you have a solution?

4:28 hiredman: so you have producers and consumers

4:28 cmvkk: yes, a big long chain of them.

4:28 hiredman: connecting them, a LinkedBlockingQueue

4:28 which, blocks if empty

4:28 cmvkk: ooh

4:29 that sounds promising

4:29 hiredman: ~jdoc java.util.concurrent.LinkedBlockingQueue

4:30 cmvkk: I will look into that. I have issues about going from 'pulling' to 'pushing' which this might entail, but we'll see.

4:30 slashus2: ,(doc seque)

4:30 clojurebot: "([s] [n-or-q s]); Creates a queued seq on another (presumably lazy) seq s. The queued seq will produce a concrete seq in the background, and can get up to n items ahead of the consumer. n-or-q can be an integer n buffer size, or an instance of java.util.concurrent BlockingQueue. Note that reading from a seque can block if the reader gets ahead of the producer."

4:35 cmvkk: are these things thread-safe?

4:38 hiredman: that is their primary purpose

4:39 cmvkk: awesome. I think I can build something on this, thanks.

4:41 hiredman: it is very cool

4:43 cmvkk: funny that to come up with a viable system I had to eschew clojure's concurrency system in favor of java's...

4:43 hiredman: eh

4:44 just using a lbq won't make your system concurrent

4:44 cmvkk: yeah, i know

4:45 hiredman: I have been using threadpoolexecutors (which agents are built on) directly mostly, which is why I don't know much about agents

4:45 cmvkk: the closure bodies are in a macro, so instead of having the macro put them in closures and call other closures, they'll make the body loop over and over again, adding to a lbq,

4:45 then spin that loop off into its own thread, and expose the lbq to what would be the caller.

4:47 i'll have to define an explicit filter for line splits (since we can't have two different things popping off the same queue) but other than that, i shouldn't have to change the framework at all.

4:48 hiredman: you might want to send the closures to be executed on a thread pool instead of just launching them off to there own thread

4:49 cmvkk: well the problem with that is that i want them to just loop over and over again, only stopping when the queues they call are empty or the total number of samples has been reached.

4:49 i'm not sure how to do that with a fixed number of threads.

4:49 hiredman: ah

4:49 hmmm

4:50 cmvkk: unless there's a better way than that to make the system 'go'

4:51 like i said, i don't understand concurrency as well as i ought to

4:51 hiredman: I dunno

7:21 p_l: is there a way to get _java_ source generated from clojure source?

7:28 AWizzArd: p_l: Clojure code gets compiled directly to the JVMs byte code. There is no output to Java code.

7:28 p_l: AWizzArd: I know, but I want to get around a task which requires Java *sourcecode*

7:29 cause I just know I'll go mad from coding in Java

7:29 AWizzArd: You could try to use a decompiler (such as JAD) and use it on the .class files that Clojure produces when you compile your code.

7:29 Well, if this is a task, then the teacher will most likely not enjoy the output of a decompiler. It looks horrible :)

7:31 p_l: well, my previous assignment code included comments like "How *NOT* to design programs" or "THIS IS FORTRAN!!!"

7:32 and well... he did write something about "surprise me" for max grade...

7:35 I'm going to ask if I can use a different language than Java

7:36 AWizzArd: That would be the easiest thing I guess.

7:36 You can maybe impress him if you mention that it is functional programming.

7:37 p_l: Or I might go with Erlang and say "I'm gonna have one thread per customer simulated" (it's a simulation of a supermarket)

7:38 though Clojure is probably safer in terms of "will it run on teacher's pc"

7:44 AWizzArd: You could make a double clickable .jar file out of your Clojure program. It's likely that the teacher already has Java installed on her compi.

7:46 p_l: AWizzArd: He wants it submitted through BlueJ

7:52 cgray: hi, I'm getting a strange error: `java.lang.ClassFormatError: Invalid method Code length 65641 in class file user$eval__2723 (NO_SOURCE_FILE:0)'

7:53 I think it might have something to do with being low on memory...

9:57 djpowell: cgray: are you attempting to load a large datastructure into clojure with load-file or something?

10:01 if so, then you should 'read' the data in, rather than 'load' it in. reading will return a datastructure; loading will compile the expression into jvm code that returns the datastructure - which might exceed the jvm code size limitations

10:23 AWizzArd: Speed comparison: Clojure vs F# and OCaml: http://groups.google.com/group/comp.lang.functional/browse_frm/thread/99b8230c078d9b44/bb739bc7f68c3922

10:40 heanol: is there anything wrong with this code: http://pastebin.com/d7db29511 ?

10:40 i'm trying to use compojure with clojure trunk..

10:43 leafw: AWizzArd: in that speed comparison, numerous numbers are used with wrappers, no int or double casting.

10:43 particularly in the mand fn

10:44 Chouser: heanol: it looks to me like core is somehow out of date with itself. you might try a clean and rebuild of clojure.

10:44 Chousuke: it uses (= 0 i) instead of (zero? i) :)

10:49 heanol: Chouser: didn't help

10:50 Chouser: heanol: what if you just type the word 'next' at the repl?

10:50 no quotes

10:51 heanol: http://pastebin.com/da37d37e

10:51 like that?

10:52 danlarkin__: heanol: are you still on sourceforge trunk?

10:52 Chouser: ok, now try: (macroexpand '(doseq [i (range 2)] i))

10:53 heanol: danlarkin__: doh, yes

10:53 Chouser: hmph. but how was doseq producing calls to 'next'?

10:53 leafw: question about atomatic type inference: do constructors do it? Does make-array do it? I think the latter doesn't.

10:54 heanol: Chouser: (loop* [sq__3547 (clojure.core/seq (range 2))] (clojure.core/when sq__3547 (clojure.core/let [i (clojure.core/first sq__3547)] (clojure.core/when true (clojure.core/when true (do i)) (recur (clojure.core/rest sq__3547))))))

10:55 Chouser: yeah, see -- your doseq is calling 'rest' not 'next'.

10:55 are you using a pre-compiled compojure?

10:55 heanol: Chouser: nope, i compiled it myself from trunk

10:56 however, after using clojure from the google code svn instead

10:56 i get another error..

10:56 Caused by: java.lang.Exception: Unable to resolve symbol: lazy-cons in this context

10:57 i assume they're not compatible then :p

10:57 leafw: use lazy-cat instead

10:57 lazy-cons was removed.

10:57 Chouser: lazy-cat is not the same as lazy-cons

10:58 heanol: hmm.. i was using clojure-contrib from sourceforge too

10:58 Chouser: (lazy-cons [1 2] [3 4]) ==> ([1 2] 3 4)

10:59 (lazy-cat [1 2] [3 4]) ==> (1 2 3 4)

11:02 gnuvince: When's rhickey leaving for London?

11:03 rhickey: gnuvince: tomorrow

11:03 gnuvince: ok

11:03 Break a leg!

11:03 rhickey: thanks

11:09 anyone coming to QCon London or this meetup? http://www.meetup.com/Londonjavacommunity/calendar/9672764/

11:09 Holcxjo: I'll be there on Thursday

11:10 rhickey: Holcxjo: cool!

11:10 Holcxjo: Don't have that sort of money for QCon

11:10 Let me know what sort of amicable question you want me to feed you. ;-)

12:09 leafw: kotarak

12:11 cgray: one thing I'm curious about is why zip is not in the core library... it's so useful for functional programming...

12:12 or am I missing it?

12:12 Chouser: ,(map vector [1 2 3] [4 5 6])

12:12 clojurebot: ([1 4] [2 5] [3 6])

12:12 Chouser: ,(map list [1 2 3] [4 5 6])

12:12 clojurebot: ((1 4) (2 5) (3 6))

12:12 Chouser: ,(map hash-map [1 2 3] [4 5 6])

12:12 clojurebot: ({1 4} {2 5} {3 6})

12:12 Chouser: cgray: you just have to be more specific. :-)

12:13 cgray: neato

12:14 Chousuke: hmm

12:14 ,(zipmap [1 2] [3 4])

12:14 clojurebot: {2 4, 1 3}

12:14 Chousuke: ah, right, that was the difference :)

12:15 cgray: that also doesn't work like zip with keys that are the same

12:15 ,(zipmap [1 1] [3 4])

12:15 clojurebot: {1 4}

12:15 Chouser: right, because it's producing a single map -- keys must be unique

12:15 (map hash-map ...) produces a seq of hash-maps.

12:16 Chousuke: ,(reduce merge {} (map hash-map [1 2] [3 4]))

12:16 clojurebot: {2 4, 1 3}

12:16 Chouser: ,(map hash-map [1 2 3] [4 5 6] [7 8 9] '[a b c])

12:16 clojurebot: ({1 4, 7 a} {2 5, 8 b} {3 6, 9 c})

12:17 Chousuke: hmm

12:17 ,(reduce into {} (map hash-map [1 2] [3 4]))

12:17 clojurebot: {2 4, 1 3}

12:17 Chousuke: yay

12:18 ,(reduce into [] (map hash-map [1 2] [3 4]))

12:18 clojurebot: [[1 3] [2 4]]

12:36 timmcd: Hello

12:36 ^_^

12:37 leafw: anybody uses gorilla here -- it keeps opening a new Scratch buffer for every single evaluation, which is a pain

12:37 gnuvince: Ever since rhickey posted his "On the importance of recognizing and using maps", my head has been spinning

12:37 timmcd: xD

12:40 What shows more skill; coding the FizzBuzz challenge with an if/and, or multiple ifs? xD

12:42 hiredman: I have to wonder, how many people who ask about type hinting (on clojure reddit comment threads) are using ruby

12:43 gnuvince: timmcd: I say multiples. Writing it with if/and can obscure the meaing

12:44 timmcd: 3 ifs make it plainly clear, even if it violates DRY a little bit.

12:44 timmcd: Mmk, thanks.

12:44 gnuvince: timmcd: that's just me.

12:44 timmcd: Thanks

12:44 I'll be looking into internships once I finish high-school

12:44 gnuvince: hiredman: I also really like the "lacking proper tail call optimization is a showstopper" crowd.

12:45 hiredman: $%#@$%

12:46 well, it's just reddit, it's not real life or anything

12:47 timmcd: hiredman: Whats wrong with Ruby?

12:47 hiredman: timmcd: slow

12:47 timmcd: Thats true

12:47 Was helpful for learning the basics of OO for me tho

12:47 hiredman: but people still use it

12:47 timmcd: OOP, even >_<

12:47 gnuvince: x = 10 if false; print x => nil

12:47 timmcd: Isn't JRuby sort of like Clojure? Built ontop of the JVM?

12:47 hiredman: clojure is faster then ruby without type hints

12:48 ~google jruby and clojure

12:48 clojurebot: First, out of 5730 results is:

12:48 InfoQ: JRuby and Clojure - A Good Match?

12:48 http://www.infoq.com/news/2009/02/jruby-clojure

12:49 hiredman: timmcd: my point is, performance is a non-issue and they should stop being doody heads

12:49 timmcd: One reason why I want a job in a compiled language: http://xkcd.com/303/

12:50 ^_^

12:50 hiredman, Totally.

12:50 hiredman: clojure is compiled :)

12:50 everything you type at a repl is compiled to jvm byte code and then execute

12:51 timmcd: Yeah I kno

12:51 *Know

12:51 hiredman: I think the clojure answer would be something like "sorry, busy profiling"

12:52 timmcd: Is there a simple 'not' sort of operator in Clojure? Ie, in Ruby it ould be: if 0 != 1 ...

12:52 ,(doc not)

12:52 clojurebot: "([x]); Returns true if x is logical false, false otherwise."

12:52 hiredman: there is not and not=

12:52 timmcd: >_< silly e

12:52 *me

12:52 hiredman: ,(doc not=)

12:52 clojurebot: "([x] [x y] [x y & more]); Same as (not (= obj1 obj2))"

12:58 timmcd: My father, as a part of my homeschool curriculum, made me go through part of SICP, but then we switched over to giving me tasks to complete in Ruby, since I stubbornly love Ruby.

12:58 But now I realise how much I missed Scheme

12:59 *realize, even.

13:01 gnuvince: hiredman: trudat; java -Xrunhprof:cpu=times is *so* long to run

13:03 timmcd: g2g

13:03 Cya peeps!

13:27 lisppaste8: hiredman pasted "consume (queue backed lazy-seq)" at http://paste.lisp.org/display/76706

14:18 timmcd: Hello

14:18 I was wondering; how would I store code for later running?

14:18 cmvkk: what do you mean?

14:18 timmcd: I am working on an interactive-fiction engine in Clojure, and I want 'commands' to just be mappings with

14:18 :callname and :function

14:18 and then something like

14:18 (do (get command :function))

14:19 cmvkk: if you want to do it that way, you can just store a function in :function

14:19 and call it ((get command :function))

14:19 (assoc command :function (fn [] ...))

14:19 timmcd: Ah okay

14:19 Thanks ^_^

14:20 user=> (def x {:callname "hi", :function (fn [] (println "hello"))})

14:20 ,(def x {:callname "hi", :function (fn [] (println "hello"))})

14:20 clojurebot: DENIED

14:20 cmvkk: yeah, you can't def in here

14:20 timmcd: Denied?!

14:20 boo

14:20 but anyway

14:20 doing that gives me

14:21 {:callname "hi", :function #<user$fn__51 user$fn__51@3ded59>}

14:21 cmvkk: yep.

14:21 timmcd: user=> (do (get x :function)

14:21 Doesnt execute the fn

14:21 it just shows that bit of oddnes

14:21 same with just (get x :function)

14:21 cmvkk: you gotta wrap it in an extra set of parens.

14:21 timmcd: #<user$fn__51 user$fn__51@3ded59>

14:21 cmvkk: ((get x :function))

14:21 timmcd: ah

14:21 WizardofWestmarc: bah beaten to the punch *shakes fist*

14:22 timmcd: hehe

14:22 WizardofWestmarc: if you have something return a function object like you just saw

14:22 cmvkk: out of curiosity, what are you doing that (defn hello [] ...) isn't good enough?

14:22 WizardofWestmarc: put another set of parens around it and it'll treat it as a first element in clojure code, aka a function

14:23 timmcd: Well, I just wanted my commands in my if-engine to be small mappings instead of functions

14:23 slashus2: cmvkk: Yesterday when I was talking about streams: http://clojure.org/streams to mimic the exact functionality of the python function as a generator.

14:23 timmcd: that way I can loop through the vector of commands (which are just mappings) when doing input parsing

14:23 and look at the callnames to see if it matches the input

14:23 hiredman: erm

14:24 (fn ...) is a function

14:24 timmcd: I know

14:24 But its not a named function

14:24 hiredman: "I just wanted my commands in my if-engine to be small mappings instead of functions"

14:24 timmcd: Right?

14:24 hiredman: ok, sure

14:24 timmcd: I meant the 'commands' variables

14:24 Ie:

14:25 (def command-sayhi {:callname "hi", :function (fn [] ...)})

14:25 cmvkk: you're taking a string, and you want to call a specific function based on the value of the string.

14:25 it makes sense...

14:26 the other way to do it would be to make a defmulti and write your commands as methods that dispatch on the st--

14:26 and you left.

14:26 hiredman: ^-

14:26 slashus2: heh

14:28 WizardofWestmarc: Good advice scared him off <_<

14:29 cmvkk: i rewrote my backend with a linkedblockingqueue and although it seems more concurrent it doesn't actually run any faster :(

14:32 oh well. at least it will run faster for someone with 4 cores.

14:34 hiredman: how many cores do you have?

14:35 cmvkk: just two.

15:03 Lau_of_DK: Good evening gentlemen

15:04 kotarak: Salut, Monsieur le Lau de DK.

15:09 cgrand: Guten Abend Herr Lau von DK!

15:09 Lau_of_DK: cgrand mon ami!

15:10 gnuvince: Oh no! The French are here!

15:11 Lau_of_DK: Quick, everbody hide your snails!

15:17 ambient: hello, what would be a good problem to solve if i wanted to teach myself clojure?

15:17 Lau_of_DK: http://projecteuler.net/, problems 1 - 50

15:18 ambient: Lau_of_DK: i'd rather know the algorithm beforehand, but ok :)

15:18 WizardofWestmarc: ^^

15:18 that was aimed at Lau :P

15:18 ambient: it's just the language im interested in learning

15:18 WizardofWestmarc: right but solving problems is a godo way to learn it

15:18 once you solve it, there's a wiki page with other people's solutions

15:19 so you can see how they did it to compare against your own

15:19 ambient: ok, i'll do that then

15:19 Lau_of_DK: good, next question

15:21 bitbckt: What is the in-flight velocity of an unladen swallow?

15:21 WizardofWestmarc: African or European?

15:22 Lau_of_DK: Before or after lunch ?

15:22 WizardofWestmarc: and a theater around here actually showed that as a Midnight movie last weekend

15:22 bitbckt: What? I don't know that!

15:23 dnolen: ambient: converting an existing a previous program you wrote that you find useful into Clojure is another way to learn Clojure which will yield it's own insights.

15:24 gnuvince: dnolen: definitely agree with that.

15:24 I took a Python program I wrote and made a Clojure version: shorter, faster and less fragile (IMO)

15:24 ambient: im not just so sure how robust clojure is in graphics and bitstreams

15:24 * Lau_of_DK acts surprised o_O

15:25 Lau_of_DK: clojurebot: sofiaba?

15:25 clojurebot: Titim gan �ir� ort.

15:25 ambient: lot of stuff i've done uses libraries extensively

15:25 WizardofWestmarc: dnolen and gnuvince: True but it yields entirely different insights then doing fresh code

15:25 gnuvince: Lau_of_DK: doing declarative stuff is a lot easier and clean in Clojure than in Python

15:25 hiredman: clojurebot: java interop?

15:25 clojurebot: java interop is http://clojure.org/java_interop

15:25 Lau_of_DK: ambient: http://wiki.github.com/Lau-of-DK/sofiaba

15:25 WizardofWestmarc: and IME at least it's better to gain the new code insight first, then use that information to explore rewriting old code from another language

15:25 Lau_of_DK: clojurebot: sofiaba is http://wiki.github.com/Lau-of-DK/sofiaba

15:25 clojurebot: In Ordnung

15:25 Lau_of_DK: gnuvince: I know

15:27 hiredman: ambient: clojure has access to anything java

15:29 dnolen: ambient: what kind of "robustness" are you looking for?

15:29 ambient: dnolen: the language itself containing a way to do the stuff i want

15:30 Lau_of_DK: clojure is more robust than rock

15:30 hiredman: ~clojure is also more robust than rock

15:30 clojurebot: In Ordnung

15:30 WizardofWestmarc: Bleh, Algorithms in a Nutshell needs to get here so I can work on it and convert the examples to clojure.

15:30 gnuvince: ambient: you'll most likely need to go through libs in Java, but does that really affect robustness?

15:30 hiredman: java interop is a major part of clojure

15:31 ambient: i don't really know anything about clojure so i digress

15:31 hiredman: http://clojure.org/rationale

15:31 clojurebot: rationale?

15:31 clojurebot: It's greek to me.

15:31 hiredman: clojurebot: rationale is http://clojure.org/rationale

15:31 clojurebot: 'Sea, mhuise.

15:31 WizardofWestmarc: ambient: what is your current programming background?

15:32 Rich has several presentation videos that are excellent, but which offer the most is heavily dependent on where you're coming from.

15:32 ambient: i think what i meant was how easy it is in clojure to use java classes

15:32 WizardofWestmarc: very

15:32 ambient: well that's good then

15:32 WizardofWestmarc: proxy was the only thing that slowed me down at all, but that was because I was being obtuse :P

15:33 dnolen: ambient: mind-blowing trivial.

15:33 mind-blowingly i mean.

15:33 WizardofWestmarc: any java lib is fully useable via Clojure

15:33 ambient: i'm just really learning lisp and clojure seems like the best variant for me

15:33 hiredman: ,(LinkedBlockingQueue.)

15:33 clojurebot: #<LinkedBlockingQueue []>

15:33 WizardofWestmarc: ambient: do you have background in java already?

15:34 ambient: WizardofWestmarc: some

15:34 hiredman: that is the equiv of: new LinkedBlockingQueue(); in java

15:34 WizardofWestmarc: then when you've got some time, I recommend checking out clojure.blip.tv and watching the two videos on Clojure for Java programmers

15:34 ambient: WizardofWestmarc: i tried that but for some reason firefox+ubuntu x64+flash-nonfree wont show them

15:35 WizardofWestmarc: some of the syntax is out of date now but the general feel and such is still useful for the core mindset of clojure

15:35 ah

15:35 can you play .mov files?

15:35 hiredman: ambient: blip.tv will let you download the .mov file

15:35 ambient: ok i try that then

15:35 WizardofWestmarc: :)

15:36 and if you find you like Clojure enough to expect to keep using it, the Programming Clojure book, even in beta form, is already very good

15:37 slashus21: I was reading the book and he uses lazy-cons in it. He does mention that he is using the development version of clojure at the first, and recently lazy-cons went the way of the dodo.

15:37 gnuvince: slashus21: he'll fix it.

15:38 if it's not already done in beta-8

15:38 WizardofWestmarc: wasn't that fixed in Beta 8?

15:38 haven't had a chance to actually read 8 yet to see

15:38 slashus21: I am reading beta-8

15:38 dnolen: it was fixed.

15:38 there may be a couple of places where it's missing

15:38 but the actually lazy section uses lazy-seq

15:40 slashus21: P.g. 158

15:40 wait

15:40 that is lazy-cat

15:40 I misread

15:40 sorry

15:40 WizardofWestmarc: easy to do :)

15:42 catch23: anyone here use compojure and know what is the switch for forcing clj files to be reloaded on every request (so i can see changes on the fly)

15:50 cemerick: hey, I just noticed the type fn. I guess I can ditch my type-of fn, finally. :-)

15:51 not sure about the type being part of the metadata, tho

15:51 hiredman: I am not sure about all this type checking

15:51 bitbckt: I'm not sure about all this typing.

15:58 danlarkin: people do love their types

16:00 cemerick: hiredman: has nothing to do with type-checking -- the only place I have a :type field is in a multimethod-heavy lib.

16:01 hiredman: cemerick: why not, you know, dispatch on the existence of keys in the map?

16:02 rhickey: AWizzArd: are you here?

16:03 cemerick: hiredman: because the keys are the same in many cases

16:03 hiredman: *shrug*

16:05 it seems like you are deciding to treat something as a square if it has a square label on it, regardless of if it has the properties of a square or not

16:07 cemerick: well, we're hardly working with simple bags of values. Determining the appropriate :type for a particular object is a significant part of the processing of the application -- hardly something you'd want to check again on every multimethod dispatch.

16:08 hiredman: I guess that makes sense, but I still do not like it

16:09 cemerick: what would an alternative be -- assuming identical keys and a potentially very involved process for determining "type"?

16:10 hiredman: simplify the process for determining type :P

16:10 dnolen: hiredman: separation of type and what properties an object may or may not have is a good thing, for example you have the very real problem that multiple inheritance attempts to solve, for example, perhaps something has the :type ::event-protocol. This may have absolutely nothing to do with the properties the structure has, but rather the type dictates behavior.

16:13 AWizzArd: rhickey: yes

16:28 cemerick: hiredman: let me know when you manage to turn lead into gold ;-)

16:28 hiredman: will do

16:29 cemerick: dnolen: our circumstance is somewhat similar, insofar as the objects in question can play multiple "roles" depending on the configuration of the system -- so given config A, the :type of some set of objects is computed to be X, but under config B, the :type is computed to be Y

16:30 WizardofWestmarc: hm

16:30 sounds like you guys are doing AoPish things

16:31 is there any way to do multimethods based on something other then a component of what you are passing in?

16:32 dnolen: cemerick: that sounds very useful, as it's a far too common requirement in software projects with multiple deployment envrionments ;)

16:32 cemerick: WizardofWestmarc: I'll let you know what bucket we fit into when we finish figuring out how to do what we want to do! :-)

16:33 WizardofWestmarc: the :type tag is really just the cached result of a lot of computation.

16:34 durka42: WizardofWestmarc: what else would you dispatch on?

16:34 cemerick: dnolen: one of these days, I hope to be able to demo some parts of it

16:35 hiredman: WizardofWestmarc: the mulitmethod takes a fn to dispatch, so uh, you could do anything technically

16:36 dnolen: cemerick: In less powerful languages you either have to hack together a shell script, or write some gnarly inline logic. Much better to change/augment the type and use multimethods. It sounds cool, looking forward to hearing more.

16:36 WizardofWestmarc: the idea is if you have some environmental variables or the like then you can control how it fires by anything, not necessarily as mentioned above, type

16:36 just... whatever

16:37 ContextL is the Common Lisp version of AoP if you want to see an example in a Lisp style language

16:37 durka42: (= CoP AoP)?

16:38 WizardofWestmarc: That's my impression

16:38 cemerick: dnolen: it's by no means generally-applicable. It's the back end to what is currently a very gnarly DSL for controlling a document analysis engine.

16:38 p_l: CoP != AoP

16:38 cemerick: WizardofWestmarc: yeah, we do that already -- not suitable in the particular case where we use :type tags though.

16:39 p_l: to quote a certain person, after presentic AspectJ to Lisp users: "You know what, when I show this to Java programmers they stand up and give applause"

16:39 AWizzArd: WizardofWestmarc: (defmulti foo (fn [_ _] (rand-int 2))) (defmethod foo 0 [x y] (+ x y)) (defmethod foo 1 [x y] (* x y)). And then call a few times (foo 5 10).

16:40 hiredman: it caches

16:44 durka42: hiredman: it doesn't appear to cache...

16:45 hiredman: eh

16:45 I thought it did

17:09 clojure needs some kind of anamorphic brand identifier

17:09 something the japanese can make anime out of

17:11 cmvkk: clojure-tan?

17:11 ayrnieu: this was a mistake that Ruby made early on: they decide on a rock instead of a cute anime girl named 'Ruby'.

17:12 WizardofWestmarc: heh

17:12 ayrnieu: (yes, she was proposed. I supported her.)

17:12 Ruby-tan can be a spokesperson. Only pragprog got anything out of the rock.

17:13 hiredman: or foxkeh: http://www.foxkeh.com/

17:13 cmvkk: i thought you meant like this: http://en.wikipedia.org/wiki/OS-tan

17:14 hiredman: I dunno about that anamophic

17:15 alternatively, clojurbeot needs a logo

17:16 danlarkin: -1 for anime logo

17:17 hiredman: not anime, just something japanese people can latch onto and obsess about and make anime about

17:19 WizardofWestmarc: pfft, the current symbol could be a crazy symbol of power that channels dark anime magic

17:19 <_<

17:19 danlarkin: a mascot would be fun, not sure what kind of figure I identify with clojure though

17:20 pjstadig: a futuristic ninja robot

17:20 cmvkk: that can turn into a car.

17:20 hiredman: woa

17:20 pjstadig: only if it flips out and kills people

17:21 hiredman: a flock of futuristic ninja robots

17:21 you know, for concurrent fliping and killing

17:21 pjstadig: Software Transactional Flipping-Out-and-Killing

17:22 hiredman: so the clojure ? with a bunch of little robots crawling over it

17:29 maacl: Is this the right place to ask about clojure-mode ?

17:30 Chouse1: maacl: probably the best IRC channel for it, anyway.

17:30 maacl: I keep getting "File error: Cannot open load file, clojure-auto" - I have set the load-path correctly

17:36 any ideas ?

17:38 Chouse1: must not be any emacs users here tonight.

17:39 jbondeson: maacl: paste the clojure section of your .emacs file

17:40 oh, wait... i know what it is.

17:41 you have (require 'clojure-auto) in there?

17:41 should be (require 'clojure-mode) followed by (require 'swank-clojure-autoload)

17:43 maacl: jbondeson: I will give that a try

17:47 jbondeson: that worked, thanks

17:48 jbondeson: no problem

18:02 lpetit: Hello

18:03 AWizzArd: he lpe

18:03 lpetit: Do you know if an equivalent of the aand function described in "On Lisp" is already present in some form in clojure or clojure contrib ?

18:04 cmvkk: the closest thing is probably if-let

18:14 hiredman: http://www.thelastcitadel.com/_media/clojure.png?cache=cache

18:14 cmvkk: heh

18:14 hiredman: very rough, of course

18:14 cmvkk: you'll get sued by whatever toy company made those robots

18:15 hiredman: and I think whoever makes that robot toy may take issue

18:15 yeah

18:15 lpetit: Well, if-let is a bit too verbose for what I have in mind. Here is my problem : I have a lot of nested tests to verify that every nested call doesn't return nil. If a nested call returns nil, I skip the computation. So something like

18:15 (when-let [page (aand (PlatformUI/getWorkbench) (.getActiveWorkbenchWindow it) (.getActivePage it)]

18:15 ... ...)

18:15 instead of nested when-let or if-let would be great

18:15 cmvkk: well you can just define aand as a macro on top of if-let in that case.

18:16 it should just be a direct copy out of the book with the exception that you have to do the variable capture explicitly

18:16 on the other hand:

18:17 if you don't expect any of those clauses inside aand to return nil, you might be better off using -> or doto or something

18:18 lpetit: Yes, but the whole point is that I'm calling Eclipse APIs where at each call there is the possibility to reach a null value, and it is ok to then not do anything and just quietly quit without doing anything

18:19 cmvkk: okay, so you definitely want to short-circuit on nil. In that case, you'll have to roll your own macro.

18:19 lpetit: yes

18:21 hiredman: ,(-> nil (#(and % (.getBytes 5)) (#(and % (count %)))

18:21 clojurebot: EOF while reading

18:21 hiredman: ,(-> nil (#(and % (.getBytes 5)) (#(and % (count %))))

18:21 clojurebot: EOF while reading

18:21 cmvkk: heh

18:21 lpetit: some languages have a special dotted notation for this short-circuit stuff. It's dot followed by a question mark : myObject.?myParam.?myParamParam.?myProperty and if one of the steps returns nil, instead of throwing an equivalent of NPE, then nothing happens at all. Maybe I could write a variant of -> named ->? that could follow the same pattern ?

18:22 cmvkk: that would also work.

18:22 hiredman: ,(-> nil (#(and % (.getBytes 5))) (#(and % (count %)))

18:22 clojurebot: EOF while reading

18:22 hiredman: ,(-> nil (#(and % (.getBytes 5))) (#(and % (count %))))

18:22 clojurebot: nil

18:22 hiredman: geez

18:22 ,(-> "ab" (#(and % (.getBytes 5))) (#(and % (count %))))

18:22 clojurebot: java.lang.IllegalArgumentException: No matching field found: getBytes for class java.lang.Integer

18:22 cmvkk: really it would just be a macro around -> that does what hiredman is trying to do implicitly.

18:22 wrapping each clause in an and.

18:22 hiredman: ,(-> "ab" (#(and % (.getBytes %))) (#(and % (count %))))

18:22 clojurebot: 2

18:22 durka42: you could also just wrap the -> in a catch

18:23 cmvkk: then have a nil value throw an exception?

18:23 durka42: ,(-> nil #(.getBytes %))

18:23 clojurebot: java.lang.NullPointerException

18:24 lpetit: ,(-> nil .toString)

18:24 cmvkk: ah, I guess I was thinking more generally.

18:24 clojurebot: java.lang.NullPointerException

18:24 durka42: ,(try (-> nil #(.getBytes %)) (catch NullPointerException npe nil))

18:24 clojurebot: I don't understand.

18:24 cmvkk: not every clojure function you might use in something like that would throw a nullpointerexception on nil.

18:24 Chousuke: durka42: it doesn't allow catching stuff :)

18:24 durka42: yeah, i thought i remembered that

18:25 but it allows binding, which has try in it

18:25 cmvkk: true

18:25 lpetit: Well, catching an exception would also work if a NullPointerException happens inside a function call (not related to one level returning nil), so this could hide bugs in called functions

18:25 cmvkk: that's true too.

18:25 hmm, the best method is probably just to use and.

18:26 lpetit: Yes, I'll write ->? as an exercise, with the property of short-circuiting on nil

18:27 cmvkk: that actually sounds like a pretty useful function...

18:28 hiredman: ,(try (catch))

18:28 clojurebot: hiredman: Pardon?

18:28 Chousuke: ->? is maybe not the best name

18:28 since ? is for predicates

18:28 cmvkk: yeah.

18:29 and-> makes more sense to me.

18:29 Chousuke: maybe-> :P

18:29 * Chousuke is thinking of the maybe monad

18:29 hiredman: &&->

18:30 cmvkk: is that even a legal symbol?

18:30 Chousuke: sure.

18:30 hiredman: ,&&->

18:30 clojurebot: java.lang.Exception: Unable to resolve symbol: &&-> in this context

18:30 Chousuke: ,'&&->

18:30 clojurebot: &&->

18:30 hiredman: http://andand.rubyforge.org/ "guarded method invocation or safe navigation method."

18:31 Chousuke: maybe ?->

18:31 fyuryu: anyone had problems with gen-class aksing for a Java class to have a <init> method?: NoSuchMethodError: my.ns.JavaClass.<init>(Ljava/lang/Integer) ?

18:31 lpetit: Yes, the maybe monad may be the right way to do that ...

18:31 hiredman: fyuryu: pastebin it

18:34 lpetit: Chousuke: Well, && also has a particular meaning in java ... ?-> is better, as you suggested

18:35 Chousuke: it looks like a weird smiley though :D

18:35 durka42: => (with-monad maybe-m ((m-lift 3 ->) "ab" #(.getBytes %) count))

18:35 2

18:36 => (with-monad maybe-m ((m-lift 3 ->) nil #(.getBytes %) count))

18:36 nil

18:36 Chousuke: huh, m-lift works for macros too?

18:36 durka42: apparently

18:36 but you have to tell it how many arguments to take

18:36 Chousuke: well, yeah

18:37 lisppaste8: fyuryu pasted "gen-class - extending java class" at http://paste.lisp.org/display/76719

18:38 durka42: fyuryu: you told gen-class to expect two constructors, and only wrote one

18:40 hiredman: and I am pretty sure you init function needs to take the same args as the constructor

18:41 fyuryu: durka42: are you sure that's it? gen-class expects a map of new-ctor signature to sig. of the class you're extending

18:42 or my reading comprehension is near 0% today...

18:43 kotarak: fyuryu: takes it an int or a java.lang.Integer?

18:44 you can use verbatim int in the contructor map.

18:44 fyuryu: kotarak: int, is that a problem?

18:44 oh

18:44 hiredman: fyuryu: your init function

18:44 "If supplied, names a function that will be called with the arguments to the constructor."

18:44 from the :init section of gen-class

18:46 fyuryu: kotarak: changed the type to "int" and it compiled

18:46 kotarak: Java fun. :)

18:47 fyuryu: thanks guys

18:52 ahhh, damn it. The doc even mentions primitive types

18:54 didn't read the "introduction" part, because I thought it just explains what it gen-class does. That'l teach me

19:02 kotarak: fyuryu: I learned about it by looking at the source, when I needed Void/TYPE. "Huh? I can simply write void?"

19:23 lpetit: There it is : http://paste.lisp.org/display/76725

19:24 Comments welcome, I'm faaar from a macro (and lisp in general) expert

19:32 * Raynes huggles rhickey.

19:32 cmvkk: is there a reason why 'runtime macros' won't work in clojure?

19:32 Chousuke: what do you mean with runtime macros? :)

19:32 cmvkk: i.e. a macro whose expansion is determined by the actual value of one of its arguments

19:33 Chousuke: macro expansion happens at compile-time

19:33 cmvkk: they worked in CL i'm pretty sure (but wouldn't expand until runtime)

19:33 hmm, so that feature just isn't implemented.

19:34 kotarak: lpetit: It also stops on false.

19:34 Chousuke: isn't a runtime macro a function? :)

19:34 cmvkk: in CL a macro would be expanded at compile time if possible, otherwise it would be expanded as soon as the value of its argument was known. perhaps that isn't feasable in clojure.

19:34 in this case, the behavior i was hoping for wouldn't be:

19:34 Chousuke: I think it'd be confusing :/

19:35 cmvkk: the macro call appeared in code body that would be in a closure. I was hoping it would expand when the function that returns the closure was called, meaning that layer of indirection would be eliminated for that particular closure instance.

19:36 lpetit: kotarak: you're right, it's not good enough then.

19:36 cmvkk: basically, the code will be called a million times in a row, but for each instance of the call, the argument is always going to be the same value.

19:36 kotarak: lpetit: I would not use nil for transferring error information.

19:36 lisppaste8: Rayne pasted "current cparser (not relevant)." at http://paste.lisp.org/display/76727

19:37 lpetit: kotarak: sure, it's for the case where the code one may want to write would just stop on nil, by writing a cascade of (when-let) calls

19:37 dnolen: cmvkk: i'm pretty sure that Clojure's macro system and CL's macro system are almost identical in capability. They both involve the reader, not runtime magic. someone correct me if I'm wrong of course.

19:37 cmvkk: dnolen i thought so too, but the fact that this doesn't work leads me to believe otherwise...

19:37 maybe i'm wrong about CL being able to do this?

19:38 dnolen: cmvkk: i think you should paste or post your macro ;)

19:39 lisppaste8: cmvkk pasted "macro vs. fn" at http://paste.lisp.org/display/76728

19:40 cmvkk: W and Wn are exactly the same, only W is a macro. note that Wn returns the correct answer while W returns the wrong one.

19:40 which leads me to believe that accessing (class wav) from within the macro is impossible.

19:40 kotarak: cmvkk: why does this need to be a macro? (= (class ..) ..) should be (instance? ...)

19:40 cmvkk: kotarak you're right about the second thing.

19:41 the reason i want it to be a macro is that the expanded code is going to be called hundreds of thousands of times in a row on the exact same object

19:41 and having that indirection in there when it isn't really necessary will slow the program down

19:43 dreish: cmvkk: Are you sure? Do you have benchmarks on this?

19:43 cmvkk: The JVM is really good about inlining code when it will actually improve performance.

19:43 cmvkk: nope! i only expect it to improve performance by a small margin.

19:43 it mostly just bothers me because i know it CAN be resolved only once.

19:44 dreish: cmvkk: Well, by all means don't take my word for it, but I expect it won't help to make it a macro.

19:44 lisppaste8: cemerick pasted "ancestors doesn't report superclass' parents, but isa? still works?" at http://paste.lisp.org/display/76730

19:44 cemerick: The above is very strange to me ^^^

19:45 kotarak: cmvkk: why not a function which returns a function specialized on the argument, which is then used? (defn W [wav] (cond (instance? Queue wav) #(.take wav) (instance? Atom wav) #(deref atom) (fn? wav) #(wav %) ..) Something like that?

19:45 dnolen: cmvkk, functions calls are insalcmvkk, the main problem is that your macro is assuming the local wav is evaluated, this isn't true.

19:45 cemerick: it seems like (ancestors String) should include all ancestors of Object as well

19:45 dnolen: oops

19:45 sorry

19:45 hiredman: uh

19:46 hmmm

19:46 cemerick: did you try calling ancestors on Object again?

19:46 lisppaste8: cemerick annotated #76730 "forgot to include result of (ancestors Object)" at http://paste.lisp.org/display/76730#1

19:46 dnolen pasted "for cmvkk" at http://paste.lisp.org/display/76731

19:47 cemerick: hiredman: yeah, it includes ::bar

19:47 hiredman: *shrug*

19:47 dnolen: cmvkk: this takes 24.96 ms on my machine, I wouldn't worry about performance.

19:47 hiredman: dnolen: well, it adds up

19:47 cemerick: rhickey: is this behaviour of ancestors expected, or a bug? (see paste above)

19:48 cmvkk: i AM worried about performance. i already removed a single function call per element, and with 5 elements, that sped the program up 7%.

19:48 that's 16 seconds to 15 seconds.

19:48 it's not that big of a deal really...

19:48 but I still find it sort of annoying.

19:49 dnolen: cmvkk: sure, if you really want to write the proper macro, evaluate wav, it's unevaluated, that's why yr macro doesn't work.

19:49 cmvkk: with eval you mean?

19:51 kotarak: clojurebot: eval

19:51 clojurebot: eval is sometimes useful - but only sometimes

19:51 kotarak: you can't eval the argument of a function

19:52 cmvkk: kotarak: that is indeed the case.

19:52 kotarak: cmvkk: Is that point that you want to inline things?

19:52 cmvkk: kotarak: ...! there's something available to do just that isn't there.

19:52 kotarak: definline

19:53 (doc definline)

19:53 clojurebot: Experimental - like defmacro, except defines a named function whose body is the expansion, calls to which may be expanded inline as if it were a macro. Cannot be used with variadic (&) args.; arglists ([name & decl])

19:53 cmvkk: yep. i forgot about that.

20:01 lpetit: ok corrected version of ?-> : http://paste.lisp.org/display/76725#1

20:59 dnolen: anyone messed around with trampolines?

21:00 danlarkin: dnolen: I have... pretty useful

21:02 dnolen: danlarkin: I'm assuming this has to be solved with a trampoline, say I have a function, and I want to recur, but I want to recur twice with in a do form, once with (first tree) and again with the (rest tree). loop/recur won't work because recur has to be in the tail position.

21:03 danlarkin: dnolen: trampolining won't work either

21:03 cmvkk: you can't solve that with trampoline either, I don't think.

21:04 dnolen: danlarkin: cmvkk: a better way to do it then?

21:04 danlarkin: refactor your algorithm

21:04 cmvkk: just recur normally.

21:04 or that...

21:04 i was thinking "tree recursion takes up stack space, and that's all there is to it" but maybe you can refactor?

21:05 my understanding of recursive algorithms is less than complete.

21:05 danlarkin: you could possibly use a zipper, depending on what you're doing

21:06 dreish: You can't avoid accumulating some kind of stack somewhere, because your algorithm requires backtracking.

21:07 (Or, what cmvkk said.)

21:57 cooldude127: what's with this place tonight?

21:57 cmvkk: all the problems have been solved.

21:57 cooldude127: WOOHOO!

21:57 why aren't we partying?

21:57 cmvkk: too busy coding.

21:57 Chouser: it would be a sad day

21:58 cooldude127: i was busy coding earlier, but not i'm just bored

21:58 slashus2: We would just solve them again.

21:58 cooldude127: s/not/now

21:58 cmvkk: i'm considering the merits of solving my 'runtime expansion' problem in the craziest way possible.

21:59 cooldude127: cmvkk: please explain this problem, give us something to do

21:59 cmvkk: well you won't be able to do anything about it

21:59 cooldude127: NO

22:00 cmvkk: i want a function that returns a closure that accesses its enclosed variables (args to the outer fn) differently based on their type. originally i was going to do that with a runtime macro but it didn't work.

22:00 SO: what if i wrapped defn around a macro that takes the closure body, duplicates it by (number-of-args x number-of-possible-types),

22:00 cooldude127: wait a runtime macro?

22:00 cmvkk: then combs through the code and replaces the macro with the correct expansion manually for every possible combination?

22:01 then the outer fn returns the proper closure based on its args types the normal way, at run time.

22:01 it would work, but the macro would be generating expanded code on the order of 25x its original size.

22:01 it doesn't seem worth it...

22:06 cooldude127: cmvkk: this is almost certainly a sign that you're doing something the wrong way. if it gets that ugly, there has to be a better way

22:07 cmvkk: in this case there's not, other than "don't bother at all". it was mostly a matter of unnecessary optimisation.

22:08 cooldude127: yeah i've been there

22:08 trying to get too fancy

22:09 cmvkk: more like "getting things to run fast at all".

22:10 cooldude127: oh

22:10 cmvkk: it's supposed to be generating audio, but even simple waveforms take twice as long as real time to generate.

22:10 and for complicated stuff, think one minute for every ten seconds of music.

22:55 cooldude127: is there a way to just remove a namespace from an image? i want to make sure my functions are in the right order without loading a new image

22:55 s/image/instance

22:55 i guess is better terminology

22:58 answer: remove-ns (i think)

23:13 durka42: (doc remove-ns)

23:13 clojurebot: Removes the namespace named by the symbol. Use with caution. Cannot be used to remove the clojure namespace.; arglists ([sym])

23:13 durka42: i don't think that's what you want

23:13 oh, maybe it is

23:15 * durka42 misread the question

23:28 gnuvince_: Wow

23:28 Seen in the comments of a Scala video from JAOO: "DLL hell was nothing compared to Closures."

23:29 Chouser: so... unrelated.

23:34 there's not a 'alter' or 'update' fn for thread-local bindings, is there? Just 'set!'.

Logging service provided by n01se.net