#clojure log - Mar 23 2009

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

0:01 durka42: it seems this has come up

0:01 http://groups.google.com/group/clojure/browse_frm/thread/134642cc76de17f7/90ef52f8f4c68e0a?lnk=gst&q=mevery#90ef52f8f4c68e0a

0:01 page down to chouser's comments on mevery?

0:03 Mec: yup i agree

0:13 how does this make sense, i swap the argument names around, and swap the arguments i pass, and get different values

0:15 durka42: paste?

0:16 Raynes: I hate spending an hour fixing something that isn't broken.

0:16 Mec: indeed

0:17 looks like its working now who knows why

0:28 nascent16: ok, let's say i have a map of classes (def classes {:one One, :two Two}). Later on I want to do something like: (let [klass (:one classes)] (klass.))

0:28 duncanm: what's the clojure equivalent of EXACT->INEXACT from Scheme?

0:28 nascent16: but it doesn't like that

0:28 Raynes: (-> apply doc)

0:28 That was aweasome.

0:29 awesome*

0:29 duncanm: how do i convert a ratio to a number with a decimal point?

0:29 Raynes: ,(double (/ 3 2))

0:29 clojurebot: 1.5

0:29 Raynes: Like that.

0:29 duncanm: oh

0:30 nascent16: ,(/3 2)

0:30 clojurebot: Invalid token: /3

0:30 nascent16: ,(/ 3 2)

0:30 clojurebot: 3/2

0:30 Mec: ,(double 3/2)

0:30 clojurebot: 1.5

0:30 Raynes: double simply coerces the value to a double.

0:30 slashus2: ,(double (+ 1/4 1/8))

0:30 clojurebot: 0.375

0:31 nascent16: ,(+ 1/4 1/8)

0:31 clojurebot: 3/8

0:31 nascent16: (+ 1/5 1/8)

0:31 haha

0:31 duncanm: ,(ratio 0.375)

0:31 clojurebot: java.lang.Exception: Unable to resolve symbol: ratio in this context

0:31 duncanm: oh

0:32 ,(Ratio. 0.375)

0:32 clojurebot: java.lang.IllegalArgumentException: Unable to resolve classname: Ratio

0:32 durka42: nascent16: you might have to do that as sort of a macro. (eval `(new ~(:one classes)))

0:32 duncanm: so there's no INEXACT->EXACT?

0:32 slashus2: ,(rationalize 0.375)

0:32 clojurebot: 3/8

0:33 Mec: you could do (defn ration [n] (/ n (pow 10 (count (str n))))

0:33 duncanm: oh

0:33 slashus2: duncanm: That work?

0:33 Mec: ((fn ratio [n] (/ n (pow 10 (count (str n))))) .375)

0:33 durka42: nascent16: (.newInstance (:one classes))

0:33 Mec: ,((fn ratio [n] (/ n (pow 10 (count (str n))))) .375)

0:33 clojurebot: java.lang.Exception: Unable to resolve symbol: pow in this context

0:33 Mec: ,((fn ratio [n] (/ n (Math/pow 10 (count (str n))))) .375)

0:33 clojurebot: java.lang.Exception: Unable to resolve symbol: .375 in this context

0:34 Mec: sec let me do it in my repl

0:34 slashus2: ,(rationalize 0.123456)

0:34 clojurebot: 1929/15625

0:34 nascent16: durka42: yeah, that worked

0:34 thanks

0:34 duncanm: slashus2: yeah, that does

0:35 Mec: aw boo

0:35 duncanm: user=> (rationalize (double 1/4)) ;=> 1/4

0:35 slashus2: duncanm: To tell you the truth, I found it in the doc as soon as you asked. Pretty neat.

0:35 Mec: ,(rationalize Math/pi)

0:35 clojurebot: java.lang.Exception: No such namespace: Math

0:36 Mec: orly

0:36 nascent16: Mec: that's exactly what I wanted to try

0:36 duncanm: ,(rationalize Math/PI)

0:36 clojurebot: 3141592653589793/1000000000000000

0:36 nascent16: boo

0:36 Mec: lol

0:36 slashus2: right hehe

0:40 nascent16: ,(def m Math)

0:40 clojurebot: DENIED

0:40 nascent16: fine

0:41 (let [m Math] m/PI)

0:41 ,(let [m Math] m/PI)

0:41 clojurebot: java.lang.Exception: No such namespace: m

0:41 Mec: any shorthand for (map f1 (map f2 coll))

0:41 hmm #(f1 (f2 %)) lol

0:43 Raynes: (map (fn [seqstr] (remove #(= % \=) seqstr)) ["lol = haha" "rofl = omfg"]) Fancy.

0:43 nascent16: ,(let [m Math] (ns-resolve m PI))

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

0:45 duncanm: Mec: is that the same as (map (compose f1 f2) coll) ?

0:45 nascent16: ,(let [m Math] (ns-refers m))

0:45 clojurebot: java.lang.ClassCastException: java.lang.Class cannot be cast to clojure.lang.Symbol

0:45 Mec: there is no compose, but thats how you would define it

0:45 duncanm: and compose is something like (fn [x] (f1 (f2 x)))

0:45 Mec: (doc compose)

0:45 clojurebot: excusez-moi

0:46 duncanm: (defn compose [f1 f2] (fn [x] (f1 (f2 x))))

0:46 slashus2: (doc comp)

0:46 clojurebot: Takes a set of functions and returns a fn that is the composition of those fns. The returned fn takes a variable number of args, applies the rightmost of fns to the args, the next fn (right-to-left) to the result, etc.; arglists ([& fs])

0:46 duncanm: oh

0:46 there we go

0:46 (map (comp f1 f2) coll)

0:47 Mec: nice

0:52 nascent16: ,(let [m Math] (.get (.getField m "PI") m))

0:52 clojurebot: 3.141592653589793

0:52 nascent16: There's got to be a better way than that

0:54 Mec: to do what

0:55 nascent16: get static members out of a reference to a class

0:55 Mec: ,(Math/PI)

0:55 clojurebot: 3.141592653589793

0:55 Mec: oh

0:55 nascent16: yeah, but this doesn't work:

0:55 (let [m Math] m/PI)

0:55 ,(let [m Math] m/PI)

0:55 clojurebot: java.lang.Exception: No such namespace: m

0:56 replaca: nascent16: that's because you're giving it the name m/PI

0:57 that's all one thing, not a reference to the symbol you bound earlier

0:57 with the let

0:57 nascent16: I understand why it doesn't work, but I don't understand how to make it work

0:57 except for that ugly thing i did above

0:58 replaca: this seems like a pretty uncommon case, but you could write a simple function if you want to do it often

0:58 Mec: (. Math PI)

0:58 ,(. Math PI)

0:58 clojurebot: 3.141592653589793

0:58 nascent16: haha

0:59 Mec: ,(let [m Math] (. m PI))

0:59 clojurebot: java.lang.IllegalArgumentException: No matching field found: PI for class java.lang.Class

0:59 durka42: ,(let [m Math] (eval `(. ~m PI)))

0:59 clojurebot: DENIED

0:59 Mec: i can haz confusion

0:59 nascent16: so m becomes a generic Class reference, whereas Math is a specific class (java.lang.Math)

1:00 Mec: ,((let [m Math] `(. ~m PI)))

1:00 clojurebot: java.lang.ClassCastException: clojure.lang.Cons cannot be cast to clojure.lang.IFn

1:00 Mec: say what

1:00 nascent16: i'm not sure

1:00 durka42: ,(let [m Math] `(. ~m PI))

1:00 clojurebot: (. java.lang.Math sandbox/PI)

1:01 Mec: ,(let [m Math] (`(. ~m PI)))

1:01 clojurebot: java.lang.ClassCastException: clojure.lang.Cons cannot be cast to clojure.lang.IFn

1:01 Mec: ,(let [m Math] (identity \`(. ~m PI)))

1:01 clojurebot: java.lang.IllegalStateException: Var clojure.core/unquote is unbound.

1:01 Mec: ,(let [m Math] (identity `(. ~m PI)))

1:01 clojurebot: (. java.lang.Math sandbox/PI)

1:01 Mec: i quit

1:01 nascent16: haha... what's this sandbox business?

1:01 Mec: thats just the namespace instead of user

1:01 replaca: you keep trying to evaluate a list as a function

1:01 nascent16: ah

1:01 durka42: which you need eval for

1:02 replaca: you really don't ever want backquote outside a func

1:02 no, even with eval, a list isn't a function. It's a list

1:02 durka42: you need eval to treat it as code

1:02 replaca: you can eval the list itself, but that's not a different thing

1:03 ,('(1 2) 7)

1:03 clojurebot: java.lang.ClassCastException: clojure.lang.PersistentList cannot be cast to clojure.lang.IFn

1:03 replaca: is basically what you were trying there

1:04 danlarkin: I'm slightly confused as to why (. Math PI) isn't good enough for you?

1:04 nascent16: let's say I had a variety of options for which PI was all different

1:04 MyMath YourMath HisMath

1:04 and depending on which Math was chosen, I want to use the correct value of PI

1:04 danlarkin: ,(#(. %1 %2) Math PI)

1:04 clojurebot: java.lang.Exception: Unable to resolve symbol: PI in this context

1:05 replaca: I think that Rich has really special-cased <classname>/<static> and . in a way that doesn't work generally

1:05 danlarkin: barf

1:06 nascent16: ,(#(. %1 %2) Math 'PI)

1:06 clojurebot: java.lang.IllegalArgumentException: No matching field found: p2__2425 for class java.lang.Class

1:07 replaca: I think . may be doing some capture at readtime

1:07 looking at that error

1:07 danlarkin: . is a special form

1:08 so it does fanciness

1:20 Mec: is there a way to interrupt the currently executing expresion in emacs without haveing to break and restart the lisp connection

1:20 replaca: nascent16: try this:

1:21 (defmacro getStatic [c f] `(.get (.getField ~c (name '~f)) ~c))

1:21 then, (getStatic m PI) does what you want

1:21 nascent16: nice

1:22 hardly elegant, but it looks like it'll do the trick

1:22 replaca: Mec: Chouser posted something to contrib a while back, but I don't know if anyone's tested it in emacs

1:22 Mec: I've been meaning to, but haven't gotten around to it

1:23 nascent16: the great things about macros is that they can hide various sorts of inelegance

1:23 and leave your program feeling nice and clean

1:24 technomancy: like freshly brushed teeth

1:24 nascent16: and i suppose that's the point afterall, to make these horrible machines look pretty and well behaved

2:34 vagif: Hello, anyone using slime with clojure ?

2:39 arbscht: vagif: yes

2:49 Raynes: I say kill them all and let fate sort out the mess.

3:07 vagif: arbscht: in emacs when I put cursor on function name, it shows me Evaluation Aborted. Is this how it should behave ?

3:17 Raynes: No th... Oh, he's gone.

4:13 lisppaste8: Rayne pasted "Anyone know how to indent this and make it look good? :\" at http://paste.lisp.org/display/77455

4:17 Carke: make a file->seq function and a remove= function

4:18 also i beleive (map f (map g ...)) is like (map (comp f g) ...)

4:35 Raynes: Carke: Thanks for the input. I don't think I can turn this into a comp in this specific situation however. But splitting it up into several functions makes my code look less crappy, thanks.

4:38 Cark: mhh yes you could (map (comp stringify remove=) (-> "text.txt" FileReader. BufferedReader. line-seq))

4:38 or something like that

4:38 ,(doc comp)

4:38 clojurebot: "([& fs]); Takes a set of functions and returns a fn that is the composition of those fns. The returned fn takes a variable number of args, applies the rightmost of fns to the args, the next fn (right-to-left) to the result, etc."

4:39 Raynes: Well yeah if I split those functions up as well.

4:40 Cark: (map (comp #(apply str %) (fn [s] (remove #(= \= %) s))) (-> "text.txt" FileReader. BufferedReader. line-seq))

4:40 (map (comp #(apply str %) (fn [s] (remove #(= \= %) s))) (-> "text.txt" FileReader. BufferedReader. line-seq))

4:40 hum oops

4:41 mirc is no good to edit code !

4:41 slashus2: for the last part can you just not do (line-seq (File. "text.txt"))

4:41 Raynes: slashus2: No.

4:42 (doc line-seq)

4:42 slashus2: no.

4:42 clojurebot: Returns the lines of text from rdr as a lazy sequence of strings. rdr must implement java.io.BufferedReader.; arglists ([rdr])

4:42 slashus2: oh

4:42 that is line-seq

4:42 I was seeing file-seq

4:42 * slashus2 goes to bed

4:42 Cark: ,(doc file-seq)

4:42 Raynes: Cark: Thanks, I tried that, I guess I'm just too tired and screwed something up.

4:42 clojurebot: "([dir]); A tree seq on java.io.Files"

4:42 Raynes: <3

4:43 Cark: you probably got the order wrong in your composition

4:44 Raynes: Cark: Probably mismatched parentheses actually.

4:44 I can't think very well when I'm tired.

4:45 (-> "Hi" println)

4:46 Oops, this isn't my REPL

4:46 :|

4:46 Cark: ,(-> "hi" println)

4:46 clojurebot: hi

4:46 slashus2: Raynes: We may need sleep.

4:47 Cark: ,(-> "derit" reverse #(apply str %) prinln)

4:47 clojurebot: java.lang.Exception: Unable to resolve symbol: prinln in this context

4:47 Cark: ,(-> "derit" reverse #(apply str %) println)

4:47 clojurebot: java.lang.ClassCastException: clojure.lang.Symbol cannot be cast to clojure.lang.IPersistentVector

4:48 Cark: ,(-> "derit" seq reverse #(apply str %) println)

4:48 clojurebot: java.lang.ClassCastException: clojure.lang.Symbol cannot be cast to clojure.lang.IPersistentVector

4:48 Cark: ahwell

4:49 Raynes: ,(-> "Hi there!" .toUpperCase println))

4:49 clojurebot: HI THERE!

4:49 Raynes: Oh I see.

4:50 It's bed time.

4:50 Night, thanks for the help Cark.,

4:50 Cark: gnight raynes

6:11 AWizzArd: cd #Foswiki

6:11 sorry

8:27 MikeSeth: weee clojure people

8:31 leafw: just awaking.

8:54 AWizzArd: clojurebot: max people

8:54 clojurebot: max people is 164

8:55 vdrab: I'm curious about parallel processing with pmap. Most of the programs I run these days are perl scripts that do perl things... "read lines from a file, do some processing for each line and put the results in a hash" - type of stuff. Given enough cores, is there any performance boost to be expected from wrapping the file in a seq and processing it with pmap, or will the IO overhead and low cost of processing a single line negate the benefits of parall

8:55 elization (say, on a machine with 8 cores and memory to spare)

8:56 rsynnott: if IO's the bottleneck, it will likely continue to be the bottleneck

8:56 MikeSeth: sounds like a task for hadoop et al.. though dont take my word for it

8:58 vdrab: yeah... I was just wondering whether there is any clear point at which clojure's parallelization options become really attractive for performance

9:00 I guess it's no silver bullet, but was curious to hear some use cases where you got big speedups from pmap

9:01 davatk: if you did some performance tests, I bet people would be interested.

9:02 vdrab: davatk: hehe... right, point taken.

10:32 cconstantine_: how do I use pmax? I get a "Unable to resolve symbol: pmax in this context" when I try to just use it, and I can't figure out how to reference into the parallel namespace where it appears to live

10:52 Chousuke: cconstantine_: (use 'clojure.parallel)?

10:53 cconstantine_: this needs java 1.6 doesn't it?

10:55 Chousuke: I think it needs an experimental jar.

10:55 you should read the parallel.clj file, it's documented there :P

10:56 cconstantine_: :/

11:05 thickey: cconstantine_: you need the jar here http://clojure.googlegroups.com/web/jsr166y.jar

11:08 cconstantine_: thanks

11:08 hiredman: erm

11:16 cconstantine_: has anyone considered a parallel lazy-sequence; ie, start computing the next value when returning the current value?

11:17 or even caching up to N values ahead

11:22 hiredman: ,(doc seque)

11:22 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."

11:23 cconstantine_: oh

11:23 well there ya go :)

11:27 wow, so that doesn't always help

11:27 MarkVolkmann: What is the function that returns the first item in a sequence for which a given predicate returns true?

11:29 cconstantine_: drop-while will ive you the first element that pred returns false on...

11:29 (first (drop-while (complement pred) sequence))

11:31 hiredman: ,(some (partial < 3) (range 10))

11:31 clojurebot: true

11:31 MarkVolkmann: Ah ... I just found find-first in clojure.contrib.seq-utils

11:31 hiredman: hmmm

11:31 oh

11:31 right

11:31 ,(some #(if (< 3 %) % nil) (range 10))

11:31 clojurebot: 4

11:34 hiredman: ,(some #(and (< 3 %) %) (range 10))

11:34 clojurebot: 4

11:34 hiredman: ,(meta and)

11:34 clojurebot: java.lang.Exception: Can't take value of a macro: #'clojure.core/and

11:34 hiredman: ,(meta (var and))

11:35 clojurebot: {:macro true, :ns #<Namespace clojure.core>, :name and, :file "core.clj", :line 513, :arglists ([] [x] [x & next]), :doc "Evaluates exprs one at a time, from left to right. If a form\n returns logical false (nil or false), and returns that value and\n doesn't evaluate any of the other expressions, otherwise it returns\n the value of the last expr. (and) returns true."}

11:59 hiredman: btw, if you ever want to use binding to bind a macro to another symbol, var is how you do it

12:04 cconstantine_: (var macro) returns the macro expanded?

12:04 no.. the macro as a thing. cool

12:06 so, pmax isn't exactly standard because of parallelization stuffs. Is there a non-parallel max that takes a collection instead of a set of things?

12:06 hiredman: (doc max)

12:06 clojurebot: Returns the greatest of the nums.; arglists ([x] [x y] [x y & more])

12:06 hiredman: ,(apply max (java.util.ArrayList. [1 2 3]))

12:07 clojurebot: 3

12:07 hiredman: looks like it works on collections to me

12:07 cconstantine_: right, so how do a take a collection and turn it into an argument list?

12:07 hiredman: actually, I think max was faster using reduce then apply

12:08 cconstantine_: When I call max on a list it just returns the list... do I need to convert it into something else?

12:09 hiredman: ,(binding [doc (var or)] (doc nil :a))

12:09 clojurebot: java.lang.RuntimeException: java.lang.RuntimeException: java.lang.RuntimeException: java.lang.IllegalArgumentException: Wrong number of args passed to: sandbox$my-doc

12:09 hiredman: :(

12:09 well, that usually works

12:09 cconstantine_: max does not take a list

12:09 it takes a series of things

12:09 ,(max 1 2 3)

12:09 clojurebot: 3

12:10 hiredman: you can use reduce or apply to apply max to a list

12:10 cconstantine_: ahh, I see

12:10 hiredman: ,(reduce max (range 10))

12:10 clojurebot: 9

12:10 hiredman: ,(apply max (range 10))

12:10 clojurebot: 9

12:10 cconstantine_: I missed the 'apply' in your previous thinger

12:10 hiredman: form

12:11 digash`: hiredman: i am wondering, why do you say that reduce max is faster apply max?

12:11 hiredman: digash`: because we timed it

12:12 max uses reduce internally for more then one arg

12:12 and the internal reduce produces more calls to max

12:13 so it is faster (or at least it was) to use your own reduce

12:14 digash`: hiredman: i guess i missed part of the conversation

12:14 hiredman: digash`: it was a few weeks ago

12:17 digash`: hiredman: it is still faster to call reduce, which is surprising to me

12:18 hiredman: ~def max

12:20 yeah, so the internel reduce results in something like N*1/2 more calls to max then using reduce yourself

12:22 Chousuke: hm

12:22 why?

12:23 I can't see that from the code :/

12:23 hiredman: because it calls max twice in the reduce

12:23 (reduce max (max x y) more)

12:23 Chousuke: but (max x y) is only evaluated once

12:23 hiredman: acutally

12:24 I think it may be more then N/2

12:24 oh

12:24 oh

12:24 yeah

12:24 hmmm

12:24 digash`: take a look at this

12:24 ,(time (apply max 0 0 (range 10000000)))

12:24 clojurebot: 9999999

12:24 "Elapsed time: 1958.762 msecs"

12:25 digash`: ,(time (apply max (range 10000000)))

12:25 clojurebot: 9999999

12:25 "Elapsed time: 3589.016 msecs"

12:25 Chousuke: huh?

12:25 hiredman: hah

12:26 Chousuke: ,(time (reduce max 0 (range 10000000)))

12:26 clojurebot: 9999999

12:26 "Elapsed time: 1923.614 msecs"

12:26 digash`: something strange in the jit land?

12:38 danlarkin: digash`: who knows, maybe a cronjob was running... statistical outlier... it's meaningless

12:39 hiredman: ...

12:53 cconstantine_: speaking of which.. is there an easy way to evaluate an expression multiple times and grab statistics on how long each time took to run?

12:55 AWizzArd: How can one access environment variables? (be it Windows or Unix ones)

12:56 hiredman: ,(time (dotimes [i 10000] (reduce max 0 (range 100000000))))

12:56 clojurebot: Execution Timed Out

12:56 hiredman: :(

12:57 ,(time (dotimes [i 100] (reduce max 0 (range 100000000))))

12:57 Cark: clojurebot is ronning on a zx spectrum

12:57 clojurebot: Execution Timed Out

12:57 Cark: *running

12:57 hiredman: "On the Java platform, an application uses System.getEnv to retrieve environment variable values."

12:59 AWizzArd: thx

13:00 cconstantine_: hiredman: that just gives me the time to execute that many times, I'm thinking things like min, max, avg, etc

13:01 or even just give backa list of time to execute

13:02 *list of times to execute

13:03 hiredman: *shrug*

13:03 cconstantine_: that would be really helpfull for doing timing tests

13:04 particularly if you have to interact over a network

13:05 or even just get back the time to execute of an expression as an object instead of putting it to stdout

13:05 AWizzArd: ,(first (System/getenv))

13:05 clojurebot: java.security.AccessControlException: access denied (java.lang.RuntimePermission getenv.*)

13:06 AWizzArd: cconstantine_: (dotimes [i 10] (time (print (+ 100 i))))

13:07 ,(with-out-str (dotimes [i 5] (time (+ 100 i))))

13:07 clojurebot: "\"Elapsed time: 0.046 msecs\"\n\"Elapsed time: 0.0080 msecs\"\n\"Elapsed time: 0.0040 msecs\"\n\"Elapsed time: 0.0050 msecs\"\n\"Elapsed time: 0.0040 msecs\"\n"

13:07 AWizzArd: run a regexp over this result string, collect the times and enjoy

13:07 cconstantine_: wow

13:08 that.... works. but it seems like overkill

13:08 not overkill.... overly complicated

13:08 AWizzArd: macro this complexity away

13:08 write a macro (profile (+ 10 5)) or something like that

13:08 and a function (report)

13:09 or just use an existing profiler

13:09 cconstantine_: the regex is still happening in the background

13:09 dnolen_: also time is a fairly simple macro in core.clj (5 LOC), instead of hacking around it just write your own.

13:10 pjstadig: ~def time

13:10 cconstantine_: dnolen_: that sounds like a much better option :)

13:10 Chouser_: cgrand: so have you realized yet that zip-filter's not going to cut it?

13:12 cconstantine_: in CL it's possible to return multiple values, is that possible in clojure?

13:12 bitbckt: cconstantine_: return a vector

13:12 dnolen_: or anything, the point is that you can destructure

13:13 * bitbckt nods

13:13 cconstantine_: bitbckt: right, but that means the caller has to look into the returned value. Ok. In the case of my new timing function it would be easier to not force the caller to change they way they handle the return value... I never liked multiple return values anyway

13:14 bitbckt: destructuring is idiomatic in Clojure

13:14 cconstantine_: yeah

13:14 dnolen_: if you want to include extra info some reason you could always add metadata

13:14 cconstantine_: ooooo

13:14 I like that

13:14 pjstadig: cconstantine_: jeffery chu posted a (IMO pretty briliant) example of rolling your own in Clojure http://paste.lisp.org/display/68919

13:14 cconstantine_: add the time to execute as metadata

13:14 hiredman: when I first showed up in #clojure, someone was rewriting time so it attached the time result as metadata to the result

13:14 pjstadig: multiple value return isn't exactly the same as returning a vector

13:15 cconstantine_: pjstadig: thanks

13:15 pjstadig: I think I like the meta-data thing better

13:15 Cark: question : i read on the mailing list that subvec retains the full original vector, is that true ?

13:15 hiredman: the problem with metadata is attaching it to things that don't support metadata

13:16 ~def subvec

13:16 cconstantine_: hiredman: is that a lot of stuff?

13:16 hiredman: cconstantine_: yes

13:16 cconstantine_: hiredman: oh :(

13:16 hiredman: but clojure collections support metadata

13:17 ~def clojure.lang.RT

13:17 ~def c.l.APersistentVector

13:18 Cark: looks like it does

13:18 this.v = v;

13:18 cconstantine_: hiredman: yeah... if enough stuff does it shouldn't be too bad

13:26 hiredman: clojurebot: botsnack

13:26 clojurebot: thanks; that was delicious. (nom nom nom)

13:27 bitbckt: cogito ergo nom

13:31 Chouser_: you can't put metadata on strings, numbers, or keywords. Only things that inherit from IMeta.

13:32 hiredman: ,(ancestores (class :a))

13:32 clojurebot: java.lang.Exception: Unable to resolve symbol: ancestores in this context

13:32 hiredman: ,(ancestors (class :a))

13:32 clojurebot: #{clojure.lang.Named clojure.lang.IFn java.lang.Object java.lang.Runnable java.lang.Comparable java.util.concurrent.Callable}

13:32 hiredman: ,(ancestors clojure.lang.IFn)

13:32 clojurebot: #{java.lang.Runnable java.util.concurrent.Callable}

13:33 digash``: t

13:40 cconstantine_: ew, refs don't even support metadata

13:40 Cark: ~def concat

13:43 dnolen_: cconstantine: why do need refs themselves need it?

13:43 ,(meta @(ref (with-meta {:mykey :myval} {:mymetakey :mymetaval})))

13:43 clojurebot: {:mymetakey :mymetaval}

13:43 cconstantine_: dnolen: I'm trying to think of something I can wrap non-metadata-holding types in.

14:45 cads: from inside clj, how may I find out the version of clojure i'm using?

14:52 danlarkin: cads: you can't

14:55 cads: could we write a function like that?

14:57 danlarkin: it's been proposed before... I don't think there was agreement on where the version should come from, or where it should go, at what point.. etc

14:58 Lau_of_DK: Good evening all

14:58 danlarkin: Hey Lau

15:06 tashafa: (doc with-meta)

15:06 clojurebot: Returns an object of the same type and value as obj, with map m as its metadata.; arglists ([obj m])

15:13 cads: (+ 1 2 3)

15:13 clojurebot: *suffusion of yellow*

15:15 triddell: ,(+ 1 2 3)

15:15 clojurebot: 6

15:16 triddell: cads: need a comma above ^

15:27 gnuvince: Hey, Clojure is at revision 1337!

15:28 cgrand: Chouser: the tricky part is to update a bunch of locs. The other thing is that zip-filter is a fold on the selector while, for Enlive, I'll prefer to fold over paths

15:35 hiredman: ~latest

15:35 clojurebot: latest is 1337

15:35 hiredman: it sure is

15:36 JasonCWarner: Hi room. Anyone here working on any compojure stuff?

15:42 dnolen: JasonCWarner: i'm starting to play around with it, yeah, but haven't got too far into it yet.

15:43 JasonCWarner: I'm just starting as well. Hoping to find some people to help with a problem. Can't quite figure out how to configure Jetty to serve static content (public/) with the new ring compojure code

15:44 pjstadig: i was gonna say check the wiki (because I think they have an example for serving static code, but that's probably not for the ring code)

15:44 i've played with compojure minimally

15:45 dnolen: JasonCWarner: there's a Compojure google group, people are relatively responsive, also perhaps the clojure ring project has an example on github?

15:45 pjstadig: there's a google group not sure if you've checked that out

15:45 they should have a #compojure channel

15:45 i'd hang out in there

15:56 Lau_of_DK: Can somebody explains Compojures decorators to me ?

15:56 -s

16:23 JasonCWarner: Thanks, pjstadig, joining that room now...

16:50 * digash` listening to the Panel Session: The Future of Lisp

16:51 digash`: Clojure is the future.

16:55 slashus3: digash`: Was Rich's tutorial filmed yesterday at the international lisp conference?

16:56 digash`: yes, there were cameras

16:57 slashus3: Probably will be released later.

16:58 digash`: you can probably bug Daniel Weinreb, http://www.international-lisp-conference.org/2009/committee

16:59 the whole discussion, is around clojure

17:01 hiredman: how awesome it is? how much they hate it?

17:01 digash`: i did not here any negative comment yet

17:01 hiredman: how it's a mistake and should just be another doohickey (he he hickey) tacked on to common lisp?

17:01 excellent

17:04 digash`: The first comment negative comment from Pascal "JVM and CLR must die!"

17:04 pjstadig: my only concern about all of the attention for clojure at these conferences is that it's taking away Rich's time

17:04 he's making presentations instead of hacking clojure!

17:04 slashus3: I am sure it gives him time to think.

17:05 triddell: agreed... clojure isn't where it is because Rich has been in a vacuum

17:10 digash`: Kent: "Standardisation is one big mutex."

17:14 cconstantine: I have no idea what is being said at this conference... but I see Clojure beating CL for one reason; it *has* a standard compiled distribution model (class files).

17:15 digash`: Sussman: "Language is a medium for expressing ideas clearly"

17:17 * cconstantine agrees strongly with Sussman.

17:24 cconstantine: So what does that say about most perl scripts? ;)

17:25 hiredman: you use a lot of foul language

17:27 digash`: ouch, somebody just suggested that Lisp is not popular with women.

17:29 Chousuke: Well, maybe women are just jealous, since lisp has nice curves. :P

17:29 hiredman: clojurebot: women?

17:29 clojurebot: Huh?

17:29 hiredman: clojurebot: women is <reply>women are just jealous, since lisp has nice curves. -- Chousuke

17:29 clojurebot: Roger.

17:29 stuhood: oh no

17:30 Chousuke: ;(

17:31 hiredman: clojurebot: men?

17:31 clojurebot: namespaces are (more or less, Chouser) java packages. they look like foo.bar; and corresponde to a directory foo/ containg a file bar.clj in your classpath. the namespace declaration in bar.clj would like like (ns foo.bar). Do not try to use single segment namespaces. a single segment namespace is a namespace without a period in it

17:31 hiredman: Huh

17:32 I guess that is one for the ages

17:34 digash`: "Common Lisp is a giant casserole".

17:35 bitbckt: Wow. clojurebot needs a copy editor

17:36 Chousuke: bitbckt: you can always tell it new stuff

17:36 bitbckt: Chousuke: I know.

17:37 Chousuke: meaning you can also override old definitions :P

17:37 bitbckt: Chousuke: Yes, I know.

17:39 hiredman: overriding that one would be very interesting

17:40 clojurebot: foo.bar

17:40 clojurebot: amespaces are (more or less, Chouser) java packages. they look like foo.bar; and corresponde to a directory foo/ containg a file bar.clj in your classpath. the namespace declaration in bar.clj would like like (ns foo.bar). Do not try to use single segment namespaces. a single segment namespace is a namespace without a period in it

17:40 hiredman: very interesing indeed

17:45 kefka: Hey. I think I may have found a case of insufficient parallelism w/ futures.

17:46 This should take ~0 sec to return and ~9 to display at the REPL, though it'd take 45 to display with no paralleism at all. In practice, it seems to take 25.

17:46 ,(map #(future (Thread/sleep (* 1000 %)) %) (range 10))

17:46 clojurebot: (#<Object$Future$IDeref@1ae9cec: 0> #<Object$Future$IDeref@c08964: 1> #<Object$Future$IDeref@7c06ab: 2> #<Object$Future$IDeref@9a0466: 3> #<Object$Future$IDeref@196de7e: 4> #<Object$Future$IDeref@1e9315f: 5> #<Object$Future$IDeref@a86249: 6> #<Object$Future$IDeref@ccdd53: 7> #<Object$Future$IDeref@1d69fa3: 8> #<Object$Future$IDeref@18ab25b: 9>)

17:46 kefka: Huh. The Clojure bot did it in decent time.

17:47 Have futures been altered in the past week in any way that would affect parallelism/concurrency?

17:48 On my REPL, it takes about 25 seconds to display, indicating that it's getting some (but poor) parallelism

17:48 hiredman: erm

17:48 ,(doc future)

17:48 clojurebot: "([& body]); Takes a body of expressions and yields a future object that will invoke the body in another thread, and will cache the result and return it on all subsequent calls to deref/@. If the computation has not yet finished, calls to deref/@ will block."

17:50 hiredman: are you sure you didn't leave out a zero on that test

17:51 futures are concurrent in the sense that they execute in another thread, but derefing them will block

17:51 and printing the output at the repl derefs them

17:51 so print is blocking for each thread/sleep as it goes down the seq

18:00 slashus3: ,(time (first (map #(future (Thread/sleep (* 1000 %)) %) (range 10))))

18:00 clojurebot: java.lang.Exception: Unable to resolve symbol: in this context

18:01 slashus3: ,(time (first (map #(future (Thread/sleep (* 1000 %)) %) (range 10))))

18:02 hmm

18:02 hiredman: clojurebot: ping?

18:02 clojurebot: PONG!

18:02 slashus3: not quite sure what happened there.

18:03 Well anyway, if you retrieve the second one it takes around one second, confirming the case.

18:04 the blocking deference

18:04 dereference

18:04 kefka: I think I figured the issue out. It's that map is lazy.

18:04 err, I mean map returns a lazy sequence

18:05 slashus3: kefka: Where was the problem?

18:05 kefka: if you evaluate the futures as the map runs, they go off sequentially -> poor performance.

18:06 If you don't force the seq produced by the map to be consumed at time 0 (or as close as possible) the futures aren't instantiated at time 0, so you get poor performance.

18:06 But this will run in about 0.9 seconds, as it should:

18:07 Edit: never mind. I didn't find it.

18:07 Here's something that should run in 0.9 sec, but takes 4.5

18:07 ,(time (apply + (map deref (map #(future (Thread/sleep (* 100 %)) %) (range 10)))))

18:07 clojurebot: 45

18:07 "Elapsed time: 4511.046 msecs"

18:08 kefka: ,(time (apply + (pmap deref (pmap #(future (Thread/sleep (* 100 %)) %) (range 10)))))

18:08 clojurebot: 45

18:08 "Elapsed time: 1114.229 msecs"

18:09 kefka: So it works properly with pmap, but that shouldn't matter, because the function future should be returning immediately, allowing the next future to start.

18:09 slashus3: kefka: Running that map on my computer takes 25 seconds too.

18:09 Chousuke: slashus3: are you sure you have multiple cores? :P

18:10 ah, wait, guess that shouldn't matter ;(

18:10 slashus3: I don't have multiple cores.

18:10 On this computer.

18:11 If it is derefing the objects one by one shouldn't it be 10 seconds?

18:11 wait

18:11 no

18:12 That is correct.

18:12 kefka: ,(time (apply + (map deref (pmap #(future (Thread/sleep (* 100 %)) %) (range 10)))))

18:13 clojurebot: 45

18:13 "Elapsed time: 1505.738 msecs"

18:13 kefka: ,(time (apply + (pmap deref (pmap #(future (Thread/sleep (* 100 %)) %) (range 10)))))

18:13 clojurebot: 45

18:13 "Elapsed time: 1104.012 msecs"

18:13 kefka: ,(time (apply + (pmap deref (map #(future (Thread/sleep (* 100 %)) %) (range 10)))))

18:13 clojurebot: 45

18:13 "Elapsed time: 1504.964 msecs"

18:13 kefka: ,(time (apply + (map deref (map #(future (Thread/sleep (* 100 %)) %) (range 10)))))

18:13 clojurebot: 45

18:13 "Elapsed time: 4511.04 msecs"

18:14 kefka: ,(time (apply + (map deref (into [] (map #(future (Thread/sleep (* 100 %)) %) (range 10))))))

18:14 clojurebot: 45

18:14 "Elapsed time: 902.647 msecs"

18:14 hiredman: ,(time (apply + (seque 10 (map #(future (Thread/sleep (* 100 %)) %) (range)))))

18:14 clojurebot: java.lang.IllegalArgumentException: Wrong number of args passed to: core$range

18:14 hiredman: ,(time (apply + (seque 10 (map #(future (Thread/sleep (* 100 %)) %) (range 10)))))

18:14 clojurebot: java.lang.ClassCastException: clojure.proxy.java.lang.Object$Future$IDeref cannot be cast to java.lang.Number

18:14 kefka: Huh. So I get best performance when I send it right into a vector, instead of using the Lazy-seq.

18:14 hiredman: ,(time (apply + (seque 10 (map #(deref (future (Thread/sleep (* 100 %)) %)) (range 10)))))

18:14 kefka: ,(doc seque)

18:14 clojurebot: 45

18:14 "Elapsed time: 4513.484 msecs"

18:14 "([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."

18:16 slashus3: ,(time (map #(future (Thread/sleep 1000) %) (range 10)))

18:16 clojurebot: (#<Object$Future$IDeref@1a142ec: 0> #<Object$Future$IDeref@26d149: 1> #<Object$Future$IDeref@76481e: 2> #<Object$Future$IDeref@178c581: 3> #<Object$Future$IDeref@1eea016: 4> #<Object$Future$IDeref@150262b: 5> #<Object$Future$IDeref@f9de08: 6> #<Object$Future$IDeref@600ee8: 7> #<Object$Future$IDeref@72add8: 8> #<Object$Future$IDeref@f36617: 9>)

18:16 "Elapsed time: 0.474 msecs"

18:16 slashus3: oh

18:17 Why does that take 5 seconds on my machine to print out?

18:17 kefka: You don't get a useful time unless you time something that requires derefing it.

18:18 Otherwise, it returns immediately though computation is still going on, so your quoted time is short.

18:18 e.g. this:

18:18 ,(time (apply + (map deref (into [] (map #(future (Thread/sleep (* 100 %)) %) (range 10))))))

18:18 clojurebot: 45

18:18 "Elapsed time: 910.095 msecs"

18:18 slashus3: kefka: On my machine it takes about 5 seconds

18:18 kefka: The one I did?

18:18 slashus3: The one I posted.

18:19 kefka: Yeah, it seems the work-around is to put the futures into a vector and then map deref across that vector

18:19 slashus3: When I do reduce + and map deref to it it takes 10 seconds.

18:19 So that is correct.

18:19 kefka: Try the one I just did. Tell me what you get.

18:19 slashus3: same

18:19 920

18:20 kefka: I get 910.

18:20 Yeah, so what's happening is that if you don't force the futures by doing something with the map-- the (into [] %) works-- you don't get the futures to go off immediately.

18:20 slashus3: Wonder why it is 5 seconds. I don't see where that is coming from on mine.

18:21 kefka: It's because map is lazy.

18:21 So the futures don't start running until the last one has returned.

18:21 It's not actually a bug, I don't think, since map is supposed to return something lazy

18:21 hiredman: clojurebot: map?

18:21 clojurebot: map is *LAZY*

18:22 slashus3: So that time is inaccurate.

18:22 because of the laziness

18:23 kefka: Yes, but it still takes 4.5 seconds if you don't force the futures to start immediately.

18:23 ,(map #(future (Thread/sleep (* 100 %)) %) (range 10)) ;; takes 4.5 seconds

18:23 clojurebot: (#<Object$Future$IDeref@14563d4: 0> #<Object$Future$IDeref@9d10ab: 1> #<Object$Future$IDeref@1b18970: 2> #<Object$Future$IDeref@b6481e: 3> #<Object$Future$IDeref@138c394: 4> #<Object$Future$IDeref@1b0595c: 5> #<Object$Future$IDeref@bac49a: 6> #<Object$Future$IDeref@1c1902d: 7> #<Object$Future$IDeref@e09a07: 8> #<Object$Future$IDeref@1a07a6f: 9>)

18:23 hiredman: calling it inaccurate because it does exactly what the docstrings say it does?

18:24 slashus3: It is accurate. Just confusing.

18:24 laziness is hard

18:24 hiredman: clojurebot: lazy?

18:24 kefka: ,(into [] (map #(future (Thread/sleep (* 100 %) %)) (range 10))) ;; takes ~0.9 seconds

18:24 clojurebot: lazy is hard

18:24 [#<Object$Future$IDeref@d547f8: nil> #<Object$Future$IDeref@67fb9f: nil> #<Object$Future$IDeref@1c48403: nil> #<Object$Future$IDeref@b6e2e3: nil> #<Object$Future$IDeref@e9d39c: nil> #<Object$Future$IDeref@143b598: nil> #<Object$Future$IDeref@472c8d: nil> #<Object$Future$IDeref@be0b48: nil> #<Object$Future$IDeref@d6e0df: nil> #<Object$Future$IDeref@1456c99: nil>]

18:24 hiredman: kefka: generally, to force a lazy-seq people use dorun or doall

18:25 ,(doc dorun)

18:25 clojurebot: "([coll] [n coll]); When lazy sequences are produced via functions that have side effects, any effects other than those needed to produce the first element in the seq do not occur until the seq is consumed. dorun can be used to force any effects. Walks through the successive nexts of the seq, does not retain the head and returns nil."

18:25 kefka: ,(doc doall)

18:25 clojurebot: "([coll] [n coll]); When lazy sequences are produced via functions that have side effects, any effects other than those needed to produce the first element in the seq do not occur until the seq is consumed. doall can be used to force any effects. Walks through the successive nexts of the seq, retains the head and returns it, thus causing the entire seq to reside in memory at one time."

18:26 slashus3: doall is appropriate in this case?

18:26 hiredman: it depends

18:30 this case is just some code that does nothing

18:30 so dorun would be fine

18:30 slashus3: If you want to add up all of the numbers returned you would use doall?

18:31 hiredman: or just use reduce

18:31 slashus3: yeah

18:32 hiredman: ugh, I keep expecting excel to close my parens for me

18:32 slashus3: hehe

19:04 duderdo: Hello.

19:05 Quick question. Why does "(let [x #{}] (conj x "foo") x)" return #{}?

19:05 Chousuke: because it returns x, and x is #{}

19:06 duderdo: How do I add "foo" to x then?

19:06 Chousuke: with conj, but that will no longer be named x

19:06 clojure has no variables, just names :), in the let binding you declare "x" to be #{}, and that it will be until later rebound in a let.

19:07 the key word here is immutability.

19:07 duderdo: Sorry, I'm coming from CL :)

19:07 So if I have a collection and I want to add items to it what do I use?

19:07 And yes I will read up on clojure immutabiliy ;)

19:08 Chousuke: you don't add items to a collection. You return a new collection with the item added :)

19:09 dnolen: ,(let [x #{}] (conj x 'a))

19:09 clojurebot: #{a}

19:09 Chousuke: like that.

19:09 note, however, that x still remains #{} :)

19:10 duderdo: Right...

19:10 I need to read more I guess

19:10 Chousuke: ,(let [x #{}, y (conj "foo" x)] (= x y))

19:10 clojurebot: java.lang.ClassCastException: java.lang.String cannot be cast to clojure.lang.IPersistentCollection

19:10 Chousuke: oops

19:10 ,(let [x #{}, y (conj x "foo")] (= x y))

19:10 clojurebot: false

19:11 duderdo: I understand it doesn't work but I don't see why yet

19:11 Chousuke: it starts making sense if you stop thinking of the names you see in code as variables.

19:11 dnolen: duderdo: x is immutable, you can't change it.

19:12 Chousuke: they're simply *names*, given to some value.

19:12 like in maths, x := 3

19:13 now x = 3, but you can't change the value of x in any way; you can't change "3" to be something else.

19:13 duderdo: I see. But if I want to modify a collection and use it later, what is the procedure? The examples I see use globals which doesn't make sense to me.

19:13 Chousuke: one solution is to have a ref or two.

19:14 a reference is something that you *can* change. it's a method of indirection.

19:14 for example, if you define *today* to be a reference to the current date, the value of *today* will of course change over time.

19:15 however, once you read a value from *today*, you get something like "24.03", and *that* can not be changed

19:16 teh clojure reference type allows you to do this.

19:16 duderdo: It's making sense now. Thanks. I'm just use to using LET+PUSH from cl

19:16 Chousuke: though just for modifying a collection I wouldn't look at refs right away

19:16 just write functions that return new collections with the values added/removed/whatever.

19:17 it's fast enough :)

19:17 duderdo: I'll start thinking in that direction. Thanks Chousuke.

19:17 Chousuke: You're welcome.

19:59 cconstantine: What is the equivalent of (reduce and ...) that works?

20:00 hiredman: ,(reduce #(and % %2) ...)

20:00 clojurebot: java.lang.Exception: Unable to resolve symbol: ... in this context

20:01 hiredman: well

20:01 that is a literal equivilent

20:01 ,(doc every?)

20:01 clojurebot: "([pred coll]); Returns true if (pred x) is logical true for every x in coll, else false."

20:01 cconstantine: and is a macro... so reduce won't take it

20:01 every!

20:01 I knew tehre was something like that... and failed at finding it in the docs

20:02 hiredman: ,(every? identity [1 2 nil])

20:02 clojurebot: nil

20:02 hiredman: ,(every? identity [1 2 3])

20:02 clojurebot: true

20:03 cconstantine: ,(every? true? (list true true true)

20:03 clojurebot: EOF while reading

20:03 cconstantine: bah

20:08 durka42: ,(reduce #(and %1 %2) [1 2 3])

20:08 clojurebot: 3

20:38 digash`: "Q: What happens when amateur does programming language? A: Phd" -- Guy Steel

20:39 sellout: Yeah, that was a good one.

20:39 even better with the context of the original answer: PHP

20:59 Mec: anyone know the clojurebox key commands to eval defun or region?

21:06 cconstantine: I'm not using clojurebox (didn't know there was one), but it's C-c C-e for me

21:07 Mec: hmm that brings up some eval

21:08 cconstantine: C-c C-z opens clojure

21:08 again... for me :)

21:08 Mec: that brought up the slime-repl which for some reason isnt the actual repl evaluations go to

21:08 cconstantine: I followed http://riddell.us/tutorial/slime_swank/slime_swank.html

21:09 Mec: ok let me take a look at that

21:09 cconstantine: oh wait... that's for my linux box...

21:10 I did this for my mac http://paulbarry.com/articles/2008/07/02/getting-started-with-clojure-and-aquamacs

21:11 Mec: c-x c-e executed, but it didnt go to the repl it went to that thing at the very bottom of emacs

21:12 * Mec would kill for another editor

21:13 cconstantine: is there a clojure menu? that might show you the shortcut

21:14 Mec: there is, but no shortcuts

21:15 cconstantine: hmm

21:24 Mec: bah any thoughts on how to up the heap space size, its only taking 90meg on a 4gig system

21:25 cconstantine: it's a java param

21:25 http://hausheer.osola.com/docs/5

21:27 Mec: says it can be set in the java control panel but i know i didnt see it in there when i looked

21:27 i wouldnt know where to find the java command line in clojurebox

21:28 cconstantine: not sure... search the clojurebox file a file containing "clojure.jar"?

21:29 Mec: ah i found it

21:29 would this be considered applet or application?

21:30 well since application doesnt have a space for runtime param i guess applet

21:31 cconstantine: that's an odd distinction to make..

21:32 Mec: those are the 2 options under the java control panel

21:32 cconstantine: yeah

21:33 banisterfiend: hru bbs

21:34 Mec: bah i set it to 1gig and it still wont go above 90meg

21:34 banisterfiend: is scala better than clojure?

21:35 Mec: thems fightin words

21:36 cconstantine: Mec: modifying my clojure script with the arguments in the last link I gave you worked well for me

21:37 banisterfiend: that's an odd question to ask in #clojure... or an odd way of phrasing it

21:37 gnuvince_: banisterfiend: totally

21:37 Mec: i dont know how clojurebox starts up to add it to the command line

21:38 cconstantine: as an aside I really hate the way java handles the heap

21:38 Mec: hmm thats the problem, the java control panel wont keep the params i entered

21:38 banisterfiend: gnuvince, hey vince

21:39 cconstantine: at the very least a fixed number for max-heap is stupid... and 90 is way low

21:39 Mec: local java programs should use all available memory, theres no reason not to

21:40 cconstantine: yup

21:40 banisterfiend: gnuvince, hey vincent im downloading an iain m. banks audiobook - in particular the newest sci fi novel: Matter, but im also downloading the Algebraist audio book too.

21:41 Mec: im at my whits end, java wont accept any of the changes i make

21:42 cconstantine: Mec: Sorry I can't help more... I don't even have access to a windows box right now

21:43 Mec: no sweat, i shall beat java into submission

21:43 cconstantine: It is the kind of thing that must be physically afraid of you.

21:55 SethTisue: the whole fixed heap ceiling thing my least favorite thing about the JVM

23:20 cemerick: ~max

23:20 clojurebot: max people is 164

23:25 cemerick: ~max

23:25 clojurebot: max people is 164

Logging service provided by n01se.net