#clojure log - Nov 05 2009

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

0:22 adityo: good morning folks!

1:12 hiredman: clojurebot: ping?

1:12 clojurebot: PONG!

4:00 piccolino: I am trying to use a binding as a dynamically scoped variable, but I'm getting a compile error when I reference that variable in another lexical scope (another function that gets called by the binding's form). Is there something I can do about that?

4:00 liwp: piccolino: are you talking about the (binding ..) form?

4:00 piccolino: Yeah

4:01 arbscht: piccolino: paste your code somewhere

4:01 liwp: ~paste

4:01 clojurebot: lisppaste8, url

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

4:01 liwp: piccolino: and what's the error that you're getting?

4:03 tomoj: functions don't know about variables that are dynamically bound for them

4:03 unless you tell them

4:03 piccolino: How do I tell them?

4:03 tomoj: you'd have to declare everything that might be bound

4:04 there was a discussion about this on the compojure mailing list I think

4:04 someone wanted to do like rails where you can just refer to instance variables in the view whether they exist or not

4:04 and then dynamically bind them in the controller

4:04 but the view function won't compile if the variable doesn't exist

4:05 piccolino: Ah, OK.

4:05 That actually fixed it, thanks guys.

4:05 tomoj: hmm

4:06 piccolino: So binding doesn't do destructuring?

4:06 tomoj: if you're dynamically binding a var in another namespace, do you have to declare it fully-qualified in the other namespace that uses it?

4:08 liwp: tomoj: I wouldn't think so, if you are (use...)ng the other namespace

4:17 tomoj: well my experiments just confused me even more :(

4:32 AWizzArd: I want to typehint that my function returns an array of (primitive) bytes. Is #^bytes the right tag?

4:35 tomoj: I think it's [B

4:36 AWizzArd: funny ;)

4:36 tomoj: "[" means array, "B" means bytes

4:36 but that's the jvm, I haven't done much typehinting

4:38 Chousuke: #^bytes should work

4:38 tomoj: how do you typehint an array of objects?

4:39 #^"[Lthe.class.name" ?

4:42 cgrand: tomoj: #^"[Lthe.class.name;" (adde semi-colon)

4:42 added

4:43 carpdiem: hey guys, i've been learning clojure over the past few days (coming from a python background), and i'm having a devil of a time understanding the clojure list comprehension style

4:43 i was wondering if anyone could help me understand it

4:43 the (for ...) format is just not clicking with my brain

4:44 cgrand: (for [x coll] x) is equivalent to (seq coll)

4:44 (for [x coll] (f x)) is equivalent to (map f coll)

4:45 carpdiem: @cgrand, let me ask a simple and specific question: how would you make a list of, say, 1/n for 0<=n<100?

4:45 cgrand: (for [x coll1 y coll2] [x y]) returns the cardinal product of coll1 and coll2 (coll1 being the "outer loop")

4:46 ,(for [n (range 10] (/ 1 n))

4:46 clojurebot: Unmatched delimiter: ]

4:46 cgrand: ,(for [n (range 10)] (/ 1 n))

4:46 clojurebot: java.lang.ArithmeticException: Divide by zero

4:46 cgrand: ,(for [n (range 1 10)] (/ 1 n))

4:46 clojurebot: (1 1/2 1/3 1/4 1/5 1/6 1/7 1/8 1/9)

4:47 tomoj: (for [x aseq] (foo x)) is like [foo(x) for x in aseq], I think

4:47 though I'm a python noob

4:47 yason: Apparently hinting argument types only ensures that they're java.lang.Number? Not specifically #^Integer, #^Double, etc?

4:47 carpdiem: @cgrand - thanks

4:48 @tomoj - that's actually really helpful, thanks for the translation

4:48 tomoj: I dunno if python's list comprehensions can do cartesian products

4:48 cgrand: yason: hinting is not casting, an hint doesn't cause the compiler to add checks to ensure a avlue is of the specified type

4:49 s/avlue/value/

4:49 carpdiem: @tomoj - can you show me an example of a cartesian product with a clojure list?

4:50 AWizzArd: Chousuke: yes, seems to work

4:50 carpdiem: something simple, even with just a few terms

4:50 tomoj: ,(for [x (range 3) y (range 3)] [x y])

4:50 clojurebot: ([0 0] [0 1] [0 2] [1 0] [1 1] [1 2] [2 0] [2 1] [2 2])

4:51 yason: cgrand: I've understood that Clojure makes static, compile-time checks to ensure you don't, e.g. pass a string as some argument that's been hinted to be a number.

4:51 carpdiem: @tomoj - i see

4:51 tomoj: it binds x to the first of the first seq, then runs through the elements of the second, moves on to the second of x, etc

4:51 though you can do more

4:51 ,(for [x (range 2) y (range 2) z (range 2)] [x y z])

4:51 clojurebot: ([0 0 0] [0 0 1] [0 1 0] [0 1 1] [1 0 0] [1 0 1] [1 1 0] [1 1 1])

4:51 carpdiem: yeah, i'm starting to "see" it now

4:52 your python translation was super helpful

4:52 tomoj: also..

4:52 ,(for [[k v] {"foo" 3, "bar" 4, "baz" 5}] (str k v))

4:52 clojurebot: ("foo3" "bar4" "baz5")

4:52 tomoj: destructuring :)

4:53 yason: cgrand: (defn mult [#^Integer a #^Integer b] (* a b)) happily accepts floats, integers, bignums etc. (Or is #^Integer/TYPE the right form? Same with that, too.)

4:53 carpdiem: @tomoj - i think it'll take me another day or two before something like that reads comfortably to me

4:53 tomoj: reading it does take a while I think

4:53 the key is this

4:53 ,(seq {"foo" 3, "bar" 4, "baz" 5})

4:53 clojurebot: (["foo" 3] ["bar" 4] ["baz" 5])

4:54 cgrand: yason: when you hint something it helps the compiler in picking the right method calls when doing interop. When there's no interop hints change nothing to your code.

4:54 tomoj: I think python can do something like that as well

4:54 hmm.. maybe not

4:55 carpdiem: @tomoj - ok, i'm a little confused at what just happened there

4:55 how did clojure know to make three pairs, rather than, say, two triples?

4:55 it doesn't care about the commas, right?

4:56 tomoj: right

4:56 ,(seq {"foo" 3 "bar" 4})

4:56 clojurebot: (["foo" 3] ["bar" 4])

4:56 yason: cgrand: oh, I see, it's only useful when calling Java code. Right.

4:56 tomoj: "{}" means a map, maps map keys to values

4:57 carpdiem: ok

4:57 but when i run (doc seq), it says "returns a seq on the collection..."

4:57 what is a 'seq' ?

4:57 tomoj: when you use a map as a seq, you get a seq of key-value pairs

4:57 carpdiem: just stripping out all the key-value pairs?

4:58 tomoj: there's a video you should probably watch

4:58 cgrand: yason: and once a specific method overlod is picked it's the JVM which enforces the type at runtime

4:58 tomoj: well, at http://clojure.blip.tv/

4:58 start at the bottom of the playlist

4:59 cgrand: yason: mainly usefule calling java code but also when trying to use fast math or array ops

4:59 carpdiem: all right, i'll check that out

4:59 i've been going through the ociweb tutorial so far

4:59 yason: cgrand: okay. So, any purely native clojure function always just takes plain Objects as arguments? That means that i.e. integer/float arguments are always boxed?

4:59 cgrand: yason: right now yes

5:00 tomoj: seqs are clojure's big abstraction over all sequential data

5:00 cgrand: but starting from JRE 6r14 you can ask the JVM to try optimizing boing/unboxing away

5:00 AWizzArd: oh really?

5:00 How would that work?

5:00 tomoj: vectors, lists, maps, sets, strings, .. whatever else there is

5:01 you can access them all as seqs

5:01 carpdiem: ok

5:01 tomoj: and there is a library of functions which operate on seqs so that you can use these functions with all of these kinds of objects

5:01 in (for [x foo] ...), the foo is a seq

5:01 yason: cgrand: thanks, I'll go explore more

5:01 carpdiem: thanks, i'll go through those videos now, and come back if i have more questions :-)

5:01 tomoj: (well, it's either a seq or something that can be turned into a seq)

5:02 carpdiem: gotcha

5:02 tomoj: I think those videos are not too out of date.. right?

5:05 carpdiem: glad to have you join us :)

5:05 carpdiem: thanks

5:05 i'm enjoying clojure quite a bit so far

5:06 just need to finish wrapping my brain around the new concepts

5:06 tomoj: it's well worth it, I think

5:11 I think the only thing I remember being out of date about the seq video is rest/next

5:12 but that's not terribly important, you can just read the docs on those functions as they are now

5:12 carpdiem: kk

5:29 AWizzArd: cgrand: do you know how one can ask the JVM to optimize boxing/unboxing away?

5:29 somnium: is there a way to do (for [x xs] (somefn (for [y ys] (otherfn y)))) with one for statement?

5:30 cgrand: AWizzArd: -XX:+DoEscapeAnalysis

5:34 tomoj: somnium: sure

5:34 well

5:35 (repeat (count xs) (somefn (for [y ys] (otherfn y))))

5:35 but I guess that's not really what you meant

5:35 AWizzArd: good, thx

5:36 somnium: well, something like (for [x xs] (apply hash-map (for [[k v] ys] [k (f v)])))

5:36 tomoj: hmm

5:36 that still doesn't make sense to me

5:36 you're not using x

5:37 somnium: (well pretend then function at the end is closing over x)

5:37 tomoj: so like (for [x xs] (somefn (for [y ys] (otherfn x y)))) basically?

5:38 somnium: yeah that looks right

5:38 doing (for [x xs :let [z (for [y ys] ... seems a little silly

5:38 ;)

5:39 cgrand: AWizzArd: I think I read this flag should be on by default in a next release

5:39 tomoj: of course you could make one of them a map to have only one 'for'

5:39 but that's a cheap solution

5:39 somnium: yes, but for is so readable

5:40 tomoj: one time at an interview they asked me to change some code I wrote with multiple print statements to use only one print statement

5:40 and I gave up, couldn't do it

5:40 the answer was to have a mutable string and replace all but the last print statements with concatenations onto that mutable string

5:40 :'(

5:41 somnium: is that a 'clojure has made my mind immutable' anecdote, or something else altogether ?

5:42 tomoj: at that point I didn't know clojure, unfortunately

5:42 but they asked me "can you write this with only one print statement"

5:42 similarly you asked "can you write this with only one 'for'"

5:42 and clearly you can by rewriting it in some other way which is essentially the same, like using map

5:43 which obviously wouldn't satisfy you, right?

5:43 strange thing to me is that that was the answer they were actually looking for, a trivial rewrite that doesn't actually make any difference, but strictly satisfies the question

5:45 somnium: well, in some cases map is equivalent

5:45 but if there are some more lets or filters for is better

5:46 tomoj: I still have never used those extra features of for

5:46 somnium: to my eyes they can make involved sequence transformation look so simple it seems like cheating

5:47 tomoj: but I mean we can clearly rewrite (for [x xs] (somefn (for [y ys] (otherfn x y)))) as (for [x xs] (somefn (map #(otherfn x %) ys)))

5:47 that IS cheating :)

5:47 I mean, it's not a real answer to your question

5:47 (btw, I don't have any real answers :()

5:47 somnium: (for [x xs :let [z (:mykey x)] :when (< z 100)] (for ...

5:48 tomoj: essentially it seems like you're doing two nested maps, and I don't see how you could rewrite that as anything except two nested masp

5:48 somnium: yeah, I briefly wondered if a :for keyword could work, but it would at most save one keystroke from (for ... (for :)

5:49 tomoj: I wonder if (for [... :let [x ..] :when x] x) is faster than (filter identity? (map .....))

5:49 somnium: interesting question

5:50 ~clojurebot

5:50 clojurebot: clojurebot is like life: you make trade-offs

5:50 somnium: ~clojurebot

5:50 clojurebot: clojurebot is like life: you make trade-offs

5:50 somnium: hmm, I guess it picks responses at random

5:51 AWizzArd: cgrand: yes, that makes sense. I hope Sun will continue to improve this boxing/unboxing stuff, and maybe also add tagged numbers.

5:51 somnium: wow, the source for for is pretty hairy

5:52 tomoj: seems to be about the same

5:52 (filter identity (map even? (range 1000000))) and (for [x (range 1000000) :let [z (even? x)]] z) both take around 2s

5:54 somnium: try macroexpanding for

5:57 tomoj: heh, yeah

5:57 clojure's safeguards for macro hygiene don't help

5:57 I was thinking of writing a macro to wrap around macroexpand to give a semi-readable expansion

5:58 somnium: yeah, clojure.core could be dropped at least

5:59 tomoj: when debugging your own macros I suppose it might be useful to see namespaces on some symbols

6:00 hm, actually

6:00 somnium: I haven't had the inspiration to try to write one remotely as complicated as for thus far

6:00 tomoj: it seems swank-clojure already does this

6:00 somnium: macroexpand in place is a good way to destroy the readability of source files, I found

6:01 tomoj: (for [x xs] x) at the repl and C-c C-m with point at the beginning and you get a buffer with indented code and clojure.core removed

6:01 though all the gensyms still make it pretty unreadable

6:01 somnium: hmm, C-m seems bound to return on my setup for some reason

6:01 what's the function name?

6:01 tomoj: and the chunking

6:02 hmm

6:03 somnium: ah I got it

6:03 tomoj: C-c RET does it too

6:03 somnium: that's more expansion that I was hoping for

6:03 tomoj: slime-macroexpand-1

6:03 well, that's only one macroexpand, supposedly

6:04 C-c M-m is slime-macroexpand-all for me

6:04 somnium: looking at the source for for it seems about right

6:04 tomoj: ah yes

6:04 then the gensyms might actually make some sense I suppose

6:05 clojure's gensym stuff really blew my mind when I first saw it

6:06 somnium: what (still) gets me is how comparatively easy it is to write a sane macro based on a function, compared to generating a new class in python or ruby

6:10 the chunk-family doesn't seem to have doc strings

6:11 tomoj: I guess they are relatively new?

6:12 somnium: only docs I found were the assembla ticket, so I guess so

6:22 adityo: how will i use merge-with to merge maps {:a 1 :b 2} {:a 3 :c 4}

6:23 hoeck: adityo: like this, for example: (merge-with + {:a 1 :b 2} {:a 3 :c 4})

6:24 adityo: yeah, got it thanks hoeck :)

6:25 hoeck: adityo: np :)

6:53 AWizzArd: ,(let [x (transient [1])] (into-array Byte/TYPE (map byte (persistent! x))))

6:53 clojurebot: #<byte[] [B@f3de46>

6:53 AWizzArd: but why:

6:53 ,(let [x (transient [1])] (into-array Byte/TYPE (map byte (persistent! (conj x 2)))))

6:53 clojurebot: java.lang.ClassCastException: clojure.lang.PersistentVector$TransientVector cannot be cast to clojure.lang.IPersistentCollection

6:54 AWizzArd: ah okay, nevermind

6:54 * AWizzArd now happily uses conj!

7:00 ambalek: ,(+ 1 2)

7:00 clojurebot: 3

7:00 ambalek: clojurebot: <3

7:00 clojurebot: <3 is </3

7:00 ambalek: clojurebot: are you saying you don't love me back?

7:00 clojurebot: Huh?

7:00 ambalek: you said </3 which kind of looks like a broken heart

7:10 somnium: clojurebot: </3

7:10 clojurebot: Excuse me?

7:18 ambalek: clojurebot: don't pretend you don't understand

7:18 clojurebot: No entiendo

7:28 aatifh: I have a map like {:a nil :b 2 :c nil :d 4 :e 5} and i want to remove all the key/val whose value is nil. Anyone in just one liner elegant way?

7:30 gerry`: (filter (fn [[k v]] (not= v nil)) yourmap )

7:32 tomoj: ,(into {} (filter val {:a nil :b 2 :c nil :d 4 :e 5}))

7:32 clojurebot: {:b 2, :d 4, :e 5}

7:33 tomoj: though that will remove pairs with false as a value..

7:34 ,(into {} (remove (comp nil? val) {:a nil :b 2 :c nil :d 4 :e 5 :f false}))

7:34 clojurebot: {:b 2, :d 4, :e 5, :f false}

7:35 gerry`: ,(into {} (filter (fn [[k v]] (not= v nil)) {:a nil :b 2 :c nil :d 4 :e 5}))

7:35 clojurebot: {:b 2, :d 4, :e 5}

7:38 tomoj: ,(into {} (filter (comp (complement nil?) val) {:a nil :b 2 :c nil :d 4 :e 5 :f false}))

7:38 clojurebot: {:b 2, :d 4, :e 5, :f false}

7:39 tomoj: hehe

7:41 djpowell: i was just looking at sinatra, the web framework that influences compojure; but it seems hard to read without all the parens :)

7:42 a magic token stream

7:43 _ato: djpowell: huh... you're right

7:44 that's kind of scary

7:44 * _ato used to use Sinatra with Ruby before disconvering Clojure

7:46 _ato: Compojure is lacking an awesome logo though :p

7:46 ol3: hello, i installed clojure-mode and swank-clojure

7:47 what should i do now if I want to start normal cl slime?

7:49 tomoj: ol3: https://gist.github.com/b06ace1e874298251401

7:49 that works for me

7:49 M-x slime-clojure or M-x swank-clojure-project to start up a slime repl

7:49 M-x slime starts a cl slime

7:49 or C-u M-x slime to pick which slime you want

7:50 _ato: http://preview.compojure.org/

7:50 maybe it's not awesome, I dunno

7:53 ol3: tomoj: thanks, that what i was looking for

8:08 _ato: tomoj: very nice!

8:08 I hadn't seen that

8:08 tomoj: it's hidden away for some reason

8:08 clojurebot: for is not a loop

8:09 tomoj: I don't really understand the logo

8:09 is it a martini with a blue olive?

8:11 _ato: yeah looks like a green martini with a blue olive to me

8:11 tomoj: maybe if we are classy enough to be drinking martinis, we have good composure?

8:12 * tomoj says this as he drinks cheap whiskey and 7-up out of a plastic cup

8:13 _ato: I think it's a reference to Frank Sinatra

8:15 tomoj: aha

8:16 so a hidden nod to the sinatra framework as well?

8:16 _ato: yeah, that's my guess anyway

8:17 * _ato is also more of a whiskey guy, but I do wear a hat just like Sinatra logo :)

8:24 tomoj: I have yet to use compojure for anything other than tiny experiments

8:25 it's hard!

8:25 compojure (and I guess sinatra as well? never used it) make you actually make decisions

8:25 instead of having them all already made for you by a danish dude

8:36 * eevar2 bought whiskey yesterday. even if i usually stick to whisky

8:39 solussd: will 'memoize' work correctly with a function that alters refs?

8:40 It seems like it should not, since the input would be just the ref, not the ref's value

8:41 chouser: solussd: changing a ref is a kind of side-effect

10:33 djork: it's correct to name .clj files with_underscores.clj

10:33 right?

10:34 chouser: yes

10:34 djork: namespace/with_underscores.clj becomes (ns namespace.with-underscores)

10:34 chouser: yes

10:34 djork: k

10:34 thanks

10:34 chouser: unfortunately. :-)

10:34 lisppaste8: cemerick pasted "rhickey: NoSuchFieldError on keyword lookup (regression?)" at http://paste.lisp.org/display/89834

10:35 cemerick: hrm, that doesn't happen with deftype, tho.

10:35 AWizzArd: Is there an easier for doing this:

10:35 ,(apply hash-map (apply concat (pmap #(vector %1 %2) [:a :b :c] [1 2 3])))

10:35 clojurebot: {:a 1, :c 3, :b 2}

10:35 chouser: AWizzArd: you want pmap?

10:36 AWizzArd: yes, no mapcat please

10:36 chouser: ,(into {} (pmap #(vector %1 %2) [:a :b :c] [1 2 3]))

10:36 clojurebot: {:a 1, :b 2, :c 3}

10:36 AWizzArd: good!

10:36 chouser: ,(zipmap [:a :b :c] [1 2 3])

10:36 clojurebot: {:c 3, :b 2, :a 1}

10:37 chouser: But no pzipmap or zippmap, I'm afraid.

10:37 so you're still churning out vectors.

10:37 AWizzArd: well, my %2 will be (.foo %2)

10:37 Anniepoo: anybody know how to get enclojure to start it's repl with a special java cmd line?

10:38 AWizzArd: so, the pmap is actually doing something

10:41 notallama: (zipmap [:a :b :c] (pmap foo [1 2 3])) ?

10:41 chouser: pmap doesn't appear to use chunked seqs yet.

10:41 notallama: yes, good!

10:41 rhickey: do you want a chunked pmap?

10:42 AWizzArd: good idea notallama

10:43 chouser: what is a chunked pmap?

10:47 chouser: AWizzArd: if the input seq were chunked, each step would do a whole chunk instead of a single item.

10:51 this would reduce the thread-interaction overhead per item and reduce the threshold for the amount of work needed to be done on each item for pmap to be worthwhile.

10:59 AWizzArd: chouser: and what are the differences between a single item vs. chunk?

11:05 git question: when I want to freshly clone the NEW branch of Clojure, how would I do that?

11:09 rhickey: chouser: chunked pmap is tricky, I've tried it a couple of times without being completely happy. The fundamental problem is you can't presume a uniformity of (chunked-.non) seq type across the iteration

11:09 cemerick: you get that with a clean build all around?

11:10 cemerick: rhickey: yes, top to bottom, although I've now discovered that it only happens with two of the ~15 defclasses we have.

11:11 rhickey: method called bounds?

11:12 and ant clean, not just rebuild?

11:12 cemerick: well, it has a field *and* a method called bounds

11:12 rhickey: cemerick: that was my quesiton

11:12 cemerick: rhickey: yes, cleaned all the way down the clojure, and back up

11:12 rhickey: is that true for other fields that work?

11:12 field + method?

11:13 cemerick: yes, on the same defclass, there's a field + method called derived that works fine

11:13 oh, I'm seeing a pattern, one sec

11:19 AWizzArd: What is the "git clone" command to download Clojures "new" branch instead of master?

11:19 lisppaste8: cemerick annotated #89834 "untitled" at http://paste.lisp.org/display/89834#1

11:19 cemerick: rhickey: ^^

11:19 The-Kenny: AWizzArd: After the git clone, do "git checkout new".

11:19 drewr: AWizzArd: git checkout -b new origin/new

11:20 The-Kenny: Oh sorry, origin/new. My bad.

11:20 savanni: Hey, guys, I actually have a question today...

11:22 When I try loading clojure.contrib.test-is, I get back an error saying that clojure/test__init.class and clojure/test.clj cannot be found. Any idea why this would happen when I have access to other parts of clojure.contrib?

11:26 drewr: savanni: test-is was promoted from contrib to core a couple months ago

11:26 you may have conflicting versions of both

11:26 savanni: Oh. Well that makes sense.

11:27 rhickey: cemerick: fixed

11:28 cemerick: note this is still not full non-primitive-hinted-field support

11:28 cemerick: rhickey: meaning?

11:29 rhickey: meaning the hint is ok, but does nothing, and doesn't fail when accessed via :field

11:29 cemerick: oh, ok

11:29 rhickey: as you noted yesterday, it's not creating a String field yet

11:29 cemerick: so usages in method impl bodies will need hinting

11:29 rhickey: but the lookup thunk looked for one

11:30 cemerick: ah, I was only referring to the type on the ctor

11:30 savanni: Did test-is get move into clojure.core for clojure-1.0.0?

11:31 rhickey: cemerick: I'll have to survey how extensive a change it is to support non-primitive-local hints, it is my intention to support, but in protocol-land right now

11:40 replaca_: savanni: nope, it's post-1.0.0

11:41 savanni: Thanks. I'll need to get clojure from git, then.

11:42 replaca_: savanni: or you can get the 1.0 compatible contrib

11:43 savanni: That, too. I'm more inclined to get the latest versions, though.

11:43 replaca_: (but I just stay at HEAD and everything seems fine)

11:43 savanni: If I'm getting development versions, I'll just expect things to break occasionally. :)

11:44 chouser: savanni: you may be disappointed

11:45 savanni: You mean it rarely breaks? That would be awesome.

11:45 noidi: does anyone have any idea how to install swank-clojure at the moment?

11:46 savanni: (my statement sounds really mean, and I didn't expect it to...)

11:46 noidi: I tried following these instructions http://github.com/jochu/swank-clojure, but when I run M-x slime, I get "Symbol's value as variable is void: package-activated-list"

11:47 chouser: savanni: oh, no, it's not mean to expect a development branch to break occasionally. But in practice it's pretty rare.

11:47 and usually cgrand's fault.

11:48 :-) see, now *that* was mean.

11:48 cgrand: just kidding!

11:48 noidi: I guess I'll try the package management thing, maybe installing clojure-mode from git doesn't work anymore

11:48 rhickey: ouch!

11:48 fogus_: zing

11:49 cemerick: rhickey: That fix is confirmed. I'm hitting a couple of other related issues, as well. Do you want msgs on the list, tickets in assembla, or should I lay them on you here?

11:49 rhickey: cemerick: start here

11:49 * cgrand pouts

11:50 stuartsierra: noidi: swank-clojure is in flux at the moment, preparing for a release; try the new mailing list http://groups.google.com/group/swank-clojure/browse_frm/thread/20141a1e19c60339

11:50 lisppaste8: cemerick annotated #89834 "untitled" at http://paste.lisp.org/display/89834#2

11:50 cemerick: rhickey: ^^

11:51 chouser: cgrand: I think I've broken things about as often, and while attempting changes far less useful or significant than transient maps.

11:52 noidi: stuartsierra, cool, thanks!

11:52 stuartsierra: noidi: no problem

11:52 noidi: I guess it's a good thing that &/¤%"#¤ github ate my detailed bug report, then :P

11:54 cgrand: chouser: well it's usually what I reply when one ask me how stable the dev branch is. "pretty stable unless one of my patches got applied"

11:55 chouser: heh

11:58 stuartsierra: Anyone want multi-maps in contrib?

11:59 lisppaste8: cemerick annotated #89834 "rhickey: issue #3" at http://paste.lisp.org/display/89834#3

11:59 cemerick: That's all I have now -- thankfully, I was able to distill good examples. :-)

12:00 AWizzArd: drewr: thanks

12:06 cgrand: about messing with core data structures: stack ops on persistent vectors can be made faster by having the last item or the two last items (depending on the vector parity) stored in fields. Thus the tail array is allocated only once every two conj (or pop) and peek is direct (no array lookup).

12:09 rhickey: cemerick: first fixed, second a limitation for now (use java-compatible field names)

12:10 cgrand: sounds interesting, what about the cost for ordinary lookup? - definitely adds logic there

12:11 and complexity to seq et al

12:12 lisppaste8: stuartsierra pasted "Multimaps" at http://paste.lisp.org/display/89840

12:13 cgrand: rhickey: haven't benchmarked the idea on the actual persistent vector but on a simplest prototype. The lookup cost wasn't noticeable (the indirection cost through nodes and arrays dominates I guess)

12:17 seq support: getArrayFor(i) must return a synthetic array when i is the last or the penult (when even)

12:18 transient ops would have added complexity

12:22 rhickey: cgrand: I don;t think I'd want to take on the complexity right now, but an interesting idea

12:22 another idea I had was to have different types for the different depths, then there would be no recursion, straight-through lookup code per depth

12:24 savanni: What is a good wai to debug a NullPointerException, when I know which function it is happening in but not which variable or line is null?

12:26 cemerick: rhickey: confirmed that fix. Thank you very much. :-)

12:26 rhickey: cemerick: sure - keep em coming, that one was just an undone todo

12:27 cemerick: I'm really glad you are able to try it out - you'd be amazed at how different things are under the hood :)

12:28 e.g. completely changing the compilation of fns, (:foo x) etc

12:28 djork: oops, I just wrote clojure in my objc code

12:28 (== 0 section)

12:29 cemerick: rhickey: it's been wonderfully smooth overall. Q: given that non-primitive hints are ignored right now, are host invocations in method bodies reflective? I'm not getting reflection warnings, but I can't imagine how methods are being invoked on Object fields otherwise.

12:31 rhickey: cemerick: the hints propagate through as hints, just not as storage types, so, stored as Object, resolved as direct calls due to hinting, no reflection, just checkcast

12:31 cemerick: ah, OK

12:31 I'm really starting to like the idea of a defstatic or similar for factories.

12:31 rhickey: leave out hint you should get reflection warning

12:32 cemerick: yes, interfaces + defstatic is near ideal external interface IMO

12:32 as much as this isn't a full interop facility, it really lends to nice, clean designs

12:33 and protocols will totally rock

12:33 as soon as I can figure out MI :(

12:35 cemerick: rhickey: I had to deal with this yesterday, which was fun. Amazing what can be done in "typical Java" APIs. http://lucene.apache.org/java/2_9_0/api/core/org/apache/lucene/index/IndexWriter.html#constructor_summary

12:36 rhickey: wow

12:36 cemerick: half of them are deprecated, but nevertheless....

12:38 technomancy: lucene even seemed relatively tame for a Java API to me

12:39 after working with Hadoop... =\

12:39 cemerick: uh, yeah, hadoop is pretty mammoth in terms of API surface area

12:40 we've long since stopped using it. Nice concept, but way too much *stuff* to deal with for us.

12:40 * danlarkin cowers at the very mention of hadoop

12:40 stuartsierra: That's why I wrote clojure-hadoop :)

12:40 patrkris: does anyone here have experience with using webjure? I just want to hear some opinions on it as a web programming framework? are there any better alternatives?

12:41 cemerick: just the sysadmin junk associated with it was enough to cause us to look away.

12:41 we're liking simple JMS with couch for data endpoints at the moment

12:41 stuartsierra: with ec2 & the cloudera scripts it's not too bad

12:42 patrkris: forget my question - i really should learn to use google

12:52 jasapp: I'm having a bit of trouble with clojure.xml/parse

12:53 I think this is valid xml

12:53 <foo>\"bar</foo>

12:53 but I get an exception when I try to parse it

12:54 ,(clojure.xml/parse "<foo>bar\"</foo>")

12:54 clojurebot: java.net.MalformedURLException: no protocol: <foo>bar"</foo>

12:55 chouser: jasapp: parse wants a sax InputSource, not a string.

12:55 clojurebot: a is b

12:55 jasapp: oh, sorry

12:55 I feel silly now, I thought it took strings

12:56 The-Kenny: ,(doc clojure.xml/parse)

12:56 clojurebot: "([s] [s startparse]); Parses and loads the source s, which can be a File, InputStream or String naming a URI. Returns a tree of the xml/element struct-map, which has the keys :tag, :attrs, and :content. and accessor fns tag, attrs, and content. Other parsers can be supplied by passing startparse, a fn taking a source and a ContentHandler and returning a parser"

13:01 jasapp: ahh, much better

13:25 javuchi: hello

13:25 Joreji: Hey guys, how can I keep on calling a function over and over (in a while loop) without freezing the clojure repl?

13:25 Is there some agent/thread magick that can achieve that?

13:26 javuchi: is there going to be a stand-alone clojure ever (with no dependences for the jvm)?

13:28 patrkris: Joreji: you can send an action to an agent which itself sends an action to the same agent, whenever it wants to continue "the loop"

13:30 AWizzArd: This works fine for me:

13:30 ,(let [a (agent 15), p (promise)] (send a #(do (deliver p (+ % 5)) :ok)) @p)

13:30 clojurebot: 20

13:30 AWizzArd: But, when I make (+ % 5) to (+ % "5") then it hangs

13:31 Joreji: patrkris: If I do (while 1 (send my-agent (update))) wouldn't that fill the queue of the agent pretty fast?

13:31 AWizzArd: Can deliver maybe made so that when an exception occurs that it will throw it, instead of hanging?

13:34 patrkris: Joreji: just a sec, i'll give you an example

13:36 chouser: javuchi: what would you use it for with no libraries? Clojure depends on a host (JVM, CLR, etc.) for all IO, user interaction, etc.

13:38 javuchi: chouser: because the jvm consumes too much memory

13:38 wwood: 4

13:39 cemerick: javuchi: so you want to target C or something?

13:39 patrkris: Joreji: http://pastebin.com/m70303ad7

13:39 Joreji: just a very simple example

13:40 Joreji: you don't need a while there, because every time the action is called, it will dispatch itself to the agent again and keep it going

13:41 Joreji: and the agent queue wont fill because every time the action is executed, it is taken off the queue

13:42 Joreji: patrkris: Ah, thanks alot!

13:42 patrkris: Joreji: and the Thread/sleep is just there to pretend that we're doing some work that takes a little time

13:44 abedra: should send-off ever block?

13:46 basically i want to send an agent off every n seconds

13:46 http://gist.github.com/227280

13:46 i started here

13:46 but it blocks

13:46 patrkris: abedra: note that the action is not sent before the current action is done executing

13:46 drewr: abedra: you probably want *agent* on line 2

13:50 abedra: patkris: so I should create *agent* ahead of time?

13:50 and use that for both?

13:51 patrkris: abedra: *agent* refers to the agent currently executing

13:51 abedra: it's a special variable in clojure

13:52 chouser: javuchi: once we have clojure-in-clojure, ports to other host languages/platforms will be quite a bit easier. Perhaps someone will target ObjectiveC/iPhone or chickenscheme

13:53 Joreji: patrkris: http://pastebin.com/d5bf739ca

13:53 patrkris: For some reason I'm getting a stack overflow.

13:53 patrkris: Anything obvious which I've done wrong?

13:54 fradiavalo: is it good clojure style to have code like this? (reduce + (take 100 (repeat 5)))

13:54 chouser: fradiavalo: it's probably better just to say (* 100 5)

13:54 :-)

13:55 fradiavalo: but other than that, there's nothing wrong with your expression. What about it makes you ask?

13:56 fradiavalo: chouser: Thanks, just wondering. I am learning clojure, so quite unsure about the correct idioms.

13:56 patrkris: Joreji: i'm not exactly sure

13:57 chouser: fradiavalo: a seq-producer (like repeat) fed through a chain of filters or processors (like take, filter, remove, map, etc.) is quite common, as is collecting up that seq with a 'reduce'.

13:57 Joreji: patrkris: I also get the stack overflow if I remove the (QApplication/processEvent) call.

13:57 chouser: there's even a macro to let you write it in what may be a more comfortable order.

13:58 ,(->> 5 repeat (take 100) (reduce +))

13:58 clojurebot: 500

13:58 patrkris: Joreji: do you get the stackoverflow right away?

13:58 fradiavalo: chouser: I like the ordering without the macro better :)

13:59 Guess I like to read right to left

13:59 Joreji: patrkris: No. After like 3-5 seconds.

13:59 chouser: fradiavalo: fair enough

14:00 fradiavalo: I know a little bit of q (http://en.wikipedia.org/wiki/Q_(programming_language_from_Kx_Systems) so the right to left style seems more natural

14:00 notallama: fradiavalo: with the -> and ->> macros, i often put each form on its own line, so you'd read it top to bottom.

14:01 patrkris: Joreji: hmm... maybe it's because QApplication/processEvents doesn't take much time, and the agents effectively does a lot of sends really fast... but I'm not sure.

14:01 someone else may be able to answer this

14:01 stuartsierra: Joreji: does QApplication/processEvents block?

14:01 fradiavalo: notallama: Thats a good idea to help readability

14:02 Joreji: stuartsierra: I've removed the QApplication/processEvents. So, no.

14:02 stuartsierra: then you might be overflowing the agent's event queue

14:02 Joreji: Ah.

14:03 patrkris: my thought

14:03 exactly

14:03 Joreji: Indeed. It works if I add a (Thread/sleep 500)

14:03 Thanks guys!

14:05 stuartsierra: Joreji: looking at the definition of QApplication/processEvents, you probably don't want to call it in a busy-loop like that.

14:05 abedra: patkris: thanks, that got me further, however I want to make the agent keep firing the function

14:05 patkris: and i get an agent error after the first couple of firings

14:06 stuartsierra: Clojure agents do not directly support calling an action periodically, you need Java timers or something.

14:06 Joreji: stuartsierra: Why is that?

14:06 patrkris: abedra: what is the error?

14:06 Joreji: stuartsierra: Hm ok.

14:06 Explains why this is not working.

14:07 stuartsierra: Joreji: the docs say you can call processEvents "periodically", but you're calling it incessantly, like a while(1) loop.

14:07 technomancy: is there a reason you can only kill all agents at once rather than killing individual ones?

14:07 hiredman: http://gist.github.com/178350 <- schedule

14:07 abedra: thanks

14:08 patkris: i just get Agent has errors

14:08 Joreji: stuartsierra: Makes sense. Guess I'll have to take a look at some java timers.

14:08 abedra: but I think the scheduler would help that out

14:09 patrkris: abedra: use (agent-errors my-agent) to see the errors

14:09 ,(doc agent-errors)

14:09 clojurebot: "([a]); Returns a sequence of the exceptions thrown during asynchronous actions of the agent."

14:09 stuartsierra: technomancy: maybe because the JVM discourages you from killing individual threads?

14:09 hiredman: the binding of agent to thread is very loose

14:09 an agent's action just runs on whatever thread the threadpool hands it off to

14:11 if you want to be able to cancel async actions you might look at future

14:12 technomancy: stuartsierra: didn't realize that... (.stop (Thread. foo)) is not kosher?

14:12 stuartsierra: technomancy: The JDK docs say don't do it, I think b/c it can leave locks/monitors inconsistent.

14:13 chouser: and skip 'finally' clauses

14:13 abedra: patkris: IllegalArgumentException: Key must be integer is what gets returned there

14:14 technomancy: interesting

14:14 patrkris: abedra: well I guess you're calling something inside your action that expects an integer argument :)

14:14 Chousuke: the proper way to "stop" a thread is to have it poll for the .interrupted flag

14:15 abedra: patkris: the funny thing is that it runs twice before that happens :)

14:15 Chousuke: also if you call .interrupt on a thread while it's waiting, an exception will be raised within it.

14:15 patrkris: abedra: can you give me a pastbin of your new code?

14:19 abedra: patkris: http://pastebin.com/m4785c831

14:19 patkris: that's in the middle of trying a few things out

14:20 AWizzArd: rhickey: it seems that promises can block forever when an agent tries to deliver them with something that throws an exception. For example, paste this into your repl: (let [a (agent 15), p (promise)] (send a #(do (deliver p (+ % "5")) :ok)) @p)

14:21 patrkris: abedra: ok, first of all, the actions that you send to agents must always take the agent's state as the first argument, so you should probably just have (send-off a api-key-agent) in line 8

14:22 abedra: and in line 4, you are asking for the agent's errors, but that will fail because a is bound to the agent's state at that point, *not* the agent itself

14:22 javuchi: why CL's guys still advocates against clojure?

14:23 djork: because they are smug Lisp weenies

14:23 and they are no fun

14:23 stuartsierra: javuchi: because it doesn't have a 50-year-old spec

14:23 djork: and nobody likes to hang out with them

14:23 patrkris: abedra: and why don't you just call retrieve-api-keys directly?

14:24 javuchi: i found this:

14:24 http://www.3ofcoins.net/2009/01/30/common-lisp-clojure-and-seriousness/

14:24 drewr: how do you get *ns* bound to the namespace of the fn's var?

14:24 rhickey: AWizzArd: the exception happens before the transfer of control to deliver. What you are basically saying is, code that throws an exception before it calls deliver doesn't end up calling deliver, which, while correct, is just a program bug, not something promise/deliver can do anything about

14:24 javuchi: all what he says is that clojure is a toy because it is hosted

14:25 no other technical reasons

14:25 djork: " a serious language to a toy language."

14:25 what a dick

14:25 abedra: patkris: That's what I would like to do...

14:25 drewr: iow, (in-ns 'foo.bar) (defn baz [x y] *ns*)

14:25 stuartsierra: The CL guys don't like Clojure because they see it as a concession to the market dominance of Java.

14:25 djork: the toy language is the one where I can download a jar and fire up a Repl and slap a window on the screen with the stuff already in my OS?

14:25 abedra: patkris: basically I need to have something keep calling (retrieve-api-keys) in the background while the process is running

14:26 patrkris: abedra: and you want to do something with the retrieved value, i guess?

14:26 djork: the toy language is the one where an infinite lazy seq of prime numbers is a one-liner

14:26 abedra: patkris: no, (retrieve-api-keys) just updates an atom

14:26 djork: (my favorite clojure example ever, by the way)

14:26 noidi: "after a nuclear catastrophe, archæologists of future generations should be able to re-implement the language on any hardware, including the Calculor;"

14:26 :D

14:26 AWizzArd: rhickey: ok I understand

14:26 noidi: yes, all languages should be designed for the post-apocalyptic use case

14:27 javuchi: hehe

14:27 djork: Perl and Tcl are toys too? I guess his definition of a toy language is "one that is used to do vast amounts of real work."

14:27 stuartsierra: I like this comment: http://www.3ofcoins.net/2009/01/30/common-lisp-clojure-and-seriousness/#comment-31

14:27 javuchi: i don't see the point in going against the JVM right now that it is GPL

14:28 djork: Here's the deal: the JVM is specced out, and Clojure is open source. Done. It's just as apocalypse-proof as CL.

14:28 javuchi: djork: I've never seen a serius project in CL, do you know of one?

14:28 djork: nope

14:28 javuchi: in 20 years of existence?

14:28 djork: it's just so much work to use CL

14:28 there's no time left to build your project

14:29 stuartsierra: javuchi: AllegroGraph (huge triple store) was originally written in CL, then ported to Java :)

14:29 javuchi: what's going to happen to CL today, when multi-threading applications are going to be a must?

14:29 djork: I feel like clojure/core is not going anywhere... is that right rhickey? It's small and concise enough.

14:30 patrkris: abedra: do you want the agent itself to hold any particular state, or do you just want it to repeatedly call (retreive-api-keys) with certain intervals?

14:30 stuartsierra: djork: if you think clojure.core is not going anywhere, you haven't been paying attention :)

14:30 abedra: patkris: i just want to repeatedly call it

14:30 djork: I guess not :)

14:30 stuartsierra: djork: reify, deftype, transients...

14:31 djork: I don't mean in terms of new features

14:31 I mean things aren't going away right?

14:31 stuartsierra: djork: there will probably not be major changes to the existing core functions any time soon

14:32 djork: "At this point in Lisp’s history a standard was still 25 years in the future."

14:32 patrkris: abedra: how about something like this: http://pastebin.com/d1eef4361

14:32 djork: (the age Clojure is now)

14:33 javuchi: ok, the question now is: is somebody doing any important project based on clojure?

14:34 drewr: ,(in-ns 'foo) (defn bar [] *ns*) (in-ns 'baz) (require 'foo) (foo/bar)

14:34 clojurebot: #<Namespace foo>

14:34 javuchi: any significant application?

14:34 abedra: patkris: exactly like that, thanks so much!

14:34 fogus_: "Important" is a loaded term, but FlightCaster uses Clojure

14:34 drewr: ,(ns 'foo) (defn bar [] *ns*) (in-ns 'baz) (require 'foo) (foo/bar)

14:34 clojurebot: java.lang.ClassCastException: clojure.lang.PersistentList cannot be cast to clojure.lang.Symbol

14:34 patrkris: abedra: if you need to update the state of the agent, the last expression in its action should yields its new state.... i haven't taken that into account

14:34 drewr: ,(ns foo) (defn bar [] *ns*) (in-ns 'baz) (require 'foo) (foo/bar)

14:34 clojurebot: nil

14:34 patrkris: abedra: no problem :)

14:34 drewr: that nil seems wrong to me

14:40 mikehogye: where is the best place to ask questions about Lancet?

14:47 weissj: mikehogye: here probably :) i've worked with it some - it's not quite complete, i've made a few fixes that i don't think anyone ever accepted :)

14:48 mikehogye: weissj: in the runonce method, it seems like access to the "result" atom is not properly synced

14:48 weissj: http://github.com/stuarthalloway/lancet/blob/master/lancet.clj , lines 68 and following

14:49 chouser: drewr: switching namespaces within a single top-level form is perilous. You'll get different results if you run each of those in the repl.

14:49 mikehogye: weissj: ThreadA could execute line 83, find that @result != sentinel

14:50 weissj: then ThreadB calls reset-fn

14:50 weissj: then ThreadA derefs result

14:52 weissj: causing line 85 (and ThreadA's call to runonce) to evaluate to sentinel

14:52 weissj: mikehogye: to be honest i don't have idea idea what runonce is even for. i just require lancet as ant, and start calling things like ant/unzip, ant/move, etc

14:52 drewr: chouser: for a var that points to a fn, say foo.bar/baz, is there any way within baz to refer to find foo.bar?

14:53 mikehogye: weissj: actually, the other question I wanted to ask about Lancet is: is it usable?

14:53 drewr: I'm not switching namespaces in my real code

14:53 weissj: mikehogye: all i wanted was clojure bindings into ant, which i get without doing anything special

14:54 mikehogye: ah

14:54 weissj: ah, I'm with you

14:54 drewr: chouser: s/to find/to/

14:55 weissj: mikehogye: it's usable for me, but i did have to add a few multimethods like the ones that are already there, for example for exec's arg tag, and echo's level tag

14:55 chouser: drewr: not sure exactly what you're trying to do. Would this work? (defn baz [] (.ns #'baz))

14:55 mikehogye: weissj: any idea whether anyone else is actively working on it?

14:56 chouser: drewr: or: (def baz (let [ns *ns*] (fn baz [] ns)))

14:56 weissj: mikehogye: i emailed stuart my additions and never heard anything, and i see the current git copy still doesn't have them. so i'd say no

14:56 mikehogye: weissj: bleh

14:56 weissj: thanks

14:56 weissj: i think he used it as an example from his book and never expected anyone to really use it

14:56 mikehogye: weissj: that's a shame

14:56 technomancy: pretty sure lancet is intended just as an instructional project, not to be used for anything serious.

14:56 at least, not as a tool in itself.

14:56 weissj: technomancy: yeah, which is unfortunate because it's really useful

14:57 mikehogye: it's such a good idea, though (or, it seems like a good idea to me)

14:57 weissj: and it's almost complete

14:57 then again, if its used as an example in a book, how hard can it be to finish

14:57 i haven't finished it because i'm a noob and i haven't had time

14:57 technomancy: however there *is* an in-process project at http://github.com/technomancy/leiningen that may be more like what you're looking for

14:57 but you didn't hear that from me.

14:57 weissj: but mikehogye you can have my changes if you want em :)

14:58 notallama: if ::foo is a child of ::bar, will multimethods always prefer ::foo? or do i have to tell it to prefer ::foo?

14:58 mikehogye: weissj: I assume you're the weissjeffm on github?

14:58 drewr: chouser: ah, thanks; ns() is what I needed

14:59 weissj: mikehogye: yep

14:59 drewr: it'd be nice to do it without the #'baz, but at least it occurs near the scope

14:59 mikehogye: technomancy: is leiningen specifically for building Clojure codebases?

14:59 drewr: I'm trying to convert "foo" to the value that #'foo points to dynamically

15:00 technomancy: mikehogye: maaaaaaybe. (actually, yes.)

15:00 djork: someone asked about important projects in Clojure

15:00 flightcaster.com

15:01 built a Clojure layer on top of Hadoop and Cascading

15:01 mikehogye: technomancy: okay -- I will look at leiningen, but what I'm really dying for is Ant without the suckage

15:01 technomancy: which is to say, Lancet

15:01 djork: they do massive distributed computations in Clojure

15:01 it is pretty much their backbone

15:02 http://www.infoq.com/articles/flightcaster-clojure-rails

15:02 technomancy: mikehogye: lancet doesn't even ship with a bin script; it's definitely not meant to be used like ant.

15:04 javuchi: does clojure works on mobile devices supporting java?

15:04 for example, on my nokia 6210 mobile?

15:04 stuartsierra: javuchi: it's reported to work on Android

15:05 hiredman: javuchi: most "java" phones are j2me which is garbage :(

15:05 mikehogye: technomancy: it seems like a basic wrapper script would be fairly easy (although I've given it a grand total of about 30 seconds of thought)

15:05 chouser: It's been a long time since I've heard anyone talk about clojure on j2me -- I don't remember if people got it working or not.

15:05 javuchi: hiredman: so it doesn't work?

15:05 hiredman: chouser: it would be really hard

15:05 I think j2me is mostly java 1.4

15:06 I forget, but I don't think it even has Collections

15:06 chouser: oh. ouch.

15:06 ordnungswidrig: hi

15:06 hiredman: yeah

15:06 djork: oh well... j2me devices feel slow with pure Java in the first place

15:06 I'd hate to see Clojure

15:07 hiredman: I think that depends on the phone

15:08 I did a game of life for my blackberry and it ran fine :P

15:08 ordnungswidrig: java on my sony ericsson w800i was surpringsingly fast

15:08 Chousuke: hm

15:09 I wonder how to make ant print out the entire stacktrace

15:09 ordnungswidrig: ant?

15:09 hiredman: I think palm pre might be the only phone with real java

15:09 ordnungswidrig: ant -d?

15:09 Chousuke: I'm trying to run contrib tests with my reader and it fails and it's hiding 80 items from me and not even -v shows them

15:09 hiredman: chouser: doesn't it usually do that at the end?

15:09 Chousuke: I get a string out of bounds exception somewhere.

15:10 hiredman: I would also get an abbreviated exception inline with the test run, and then a dump of all the stacktraces at the end of the ant run

15:11 djork: I'm happy with Clojure on the desktop right now, since it's all about the Repl anyway.

15:11 clojurebot: a is b

15:12 rhickey: woah - http://code.google.com/closure/

15:12 djork: wut

15:12 you know what... the word "closure" looks funny now :)

15:12 hiredman: rhickey: yeah

15:13 chouser: ,(swap! (atom [] :validator #(or (empty? %) (number? (peek %)))) conj :oops)

15:13 clojurebot: java.lang.IllegalStateException: Invalid reference state

15:13 * hiredman is doing his daily http://search.twitter.com/search?q=clojure and closure came up

15:13 * rhickey starts work on clojure -> js -> closure -> js compiler

15:14 mikehogye: technomancy: do you know of reasons that bin scripts for Lancet (or a descendent thereof) would be difficult to write?

15:15 technomancy: mikehogye: no, and that's essentially what leiningen is, plus dependency management and some built-in clojure-specific tasks. it's not hard at all.

15:15 mikehogye: technomancy: cool. I will definitely take a look.

15:16 chouser: "it compiles from JavaScript to better JavaScript" hmph.

15:16 Chousuke: hmh

15:16 * Chousuke wonders what to do

15:17 Chousuke: the ant page says to use fork="true" but that's already set...

15:17 technomancy: mikehogye: once I get the jar task done I will polish it a bit to make it easier to install and make an announcement, but you're welcome to give it a go now.

15:20 rhickey: chouser: hmph? that sounds awesome to me, like hotspot for js, makes it easier for us

15:22 javuchi: how much memory consumes an agent?

15:22 chouser: I'm actually quite ambivalent about compiling to JavaScript.

15:22 hiredman: chouser: really? I thought most of the java tasks in build.xml did not have fork="true"

15:23 er

15:23 Chousuke:

15:23 chouser: :-)

15:23 rhickey: javascript is the new bytecode

15:23 clojurebot: new Class(x) is (Class. x)

15:23 fogus_: chouser: I've spent a lot of time in GWT, so I have similar conflicting feelings.

15:24 rhickey: unlike gwt, this seems to be the stuff they actually use

15:24 chouser: rhickey: I'll buy js is bytecode when I see debuggers that tie you back to the original source.

15:25 rhickey: good point

15:25 hiredman: hmmm

15:25 chouser: the wave team apparently uses and loves gwt

15:25 rhickey: chouser: yeah, the customized new version they had made for them addressing all shortcomings of the stuff everyone else was using

15:26 chouser: javuchi: agent uses very little memory -- it's not a whole thread or anything

15:26 rhickey: oh. :-(

15:27 javuchi: is it lightweighter tha erlang processes?

15:27 thay consume about 230 bytes

15:27 chouser: oh, I missed that Closure is from google.

15:28 fogus_: GWT has it's nice points, when viewed through the right lens

15:28 chouser: hm, the Closure inspector sounds interesting -- that might be the missing piece for debugging. We'll just need one for clojurescript

15:29 fogus_: I can see some of the benefits, but in general I'd rather write javascript than java. :-P

15:31 fogus_: chouser: I agree with you. There is a huge impedance mismatch using GWT and that's tough to swallow.

15:32 javuchi: chouser: how can i know the size of an agent?

15:32 G0SUB: a lot of people complain about the debugging facilities of Clojure + SLIME being not so awesome. what is needed to fix the situation?

15:32 hiredman: more printlns

15:32 javuchi: G0SUB: i find it nice in the last versions

15:33 froog: http://georgejahad.com/clojure/cljdb.html

15:33 G0SUB: hiredman: better sldb integration will be great :)

15:33 * froog hasn't actually tried that yet himself

15:33 hiredman: G0SUB: *shrug*

15:35 chouser: javuchi: http://www.javaworld.com/javaworld/javaqa/2003-12/02-qa-1226-sizeof.html :-P

15:35 G0SUB: rhickey: where can we get the video of your awesome talk about time at the jvm lang summit?

15:37 javuchi: chouser: so basically i need to create a million agents and measure memory consumption?

15:37 fogus_: Hrmmm. Reading about Google-Closure is making bitter.

15:38 chouser: agent is _meta + validator + watches + state + q + errors

15:38 djork: you mean (+ _meta validator watches state q errors) :)

15:39 chouser: each of those one a 32-bit JVM is probably 4 bytes, plus 8 for Object, I'd guess 32 bytes per agent

15:39 djork: er, right. of course.

15:39 RomanRoe: is anybody able to use build.clojure.org as mvn repo? It stopped working for me :-/

15:40 djork: my count is 88 bytes on my JVM

15:40 chouser: on a 64-bit JVM it's probably closer to 64 bytes.

15:40 javuchi: so it is expected to use 64 bytes on a 64bit machine

15:40 djork: OS X Snow Leopard

15:40 chouser: djork: counted how?

15:40 javuchi: 88 bytes?

15:40 thats much less than 230 bytes for process in erlang

15:40 djork: (- (mime (agent nil)) (mime nil))

15:41 err that doesn't really work right now

15:41 it's my new toy memory measuring macro

15:41 chouser: ah

15:42 djork: but (mime nil) takes 24 bytes to evaluate, and (mime (agent nil)) takes 112 bytes to evaluate

15:42 chouser: well, that's about as accurate as it's worth trying to get -- something less than 100 bytes per agent.

15:42 djork: yes

15:42 javuchi: so it is reasonable to think that we could use around 60 millions of agents with 4gb of memory?

15:42 perhaps 50 millions?

15:43 chouser: I don't know what all an erlang process has to track, but agents don't have their own stack or instruction pointer or anything like that.

15:43 An agent is just a simple one-element container with a queue of actions to perform.

15:43 tmountain: GOSUB: http://www.infoq.com/presentations/Value-Identity-State-Rich-Hickey

15:44 chouser: javuchi: as you queue up more actions, the agent will hold onto more memory until it can dequeu them.

15:44 djork: that is some zen stuff there

15:44 javuchi: so 50 millions is not very reallistic

15:45 perhaps 5 millions would be more reallistic

15:45 danlarkin: javuchi: there's no way to answer that, it depends on what the agents are doing

15:45 djork: I would think about my architecture as soon as 5 million of *anything* was being considered.

15:46 javuchi: djork: think, for example, of a massive IM server

15:47 that's when erlang is brillant

15:47 i'm think if clojure might be better???

15:47 dysinger: re: bulid.clojure.org RomanRoe I had to change the url and hadn't got around to posting an updated message to the list

15:47 ordnungswidrig: javuchi: but 5 million on a single node / server sounds too much even for erlang

15:48 dysinger: the maven url is http://build.clojure.org/snapshots now RomanRoe

15:48 hiredman: javuchi: clojure agents are not actors

15:48 djork: a massive server probably needs to be distributed, whereas clojure's strong point is concurrency

15:48 dysinger: RomanRoe: I wont mess with it again

15:48 djork: you could load balance between clojure nodes

15:49 javuchi: anyway clojure is not designed for being distributed, is it?

15:49 hiredman: 2009:Sep:22:09:02:37 rhickey : Writing a message queue? use Erlang. Writing an ordinary application? use a message queue.

15:50 RomanRoe: dysinger: thanks!

15:50 dysinger: I still like erlang too

15:50 RomanRoe: dysinger: my clojure hacking evening is safe again.... puhhhh..... ;-)

15:51 dysinger: there are things you can do with networking and clustering in erlang that are trivial compared to socket programming in java land.

15:51 djork: indeed

15:52 I'd say that if you want to, just develop your server in Clojure and then try scaling it with a message queue or something like Hadoop.

15:52 It would be a good experiment.

15:52 I don't see it going too badly either.

15:53 dysinger: I am working on a peer-2-peer work group library in clojure that will allow clusters of repls to work together. Message queues don't solve all problems neatly.

15:53 djork: mmm distributed repls

15:54 hiredman: dysinger: sounds kinda like terracotta

15:54 dysinger: minus 300k lines of code and instrumenting and XML

15:54 hiredman: :P

15:55 dysinger: no I don't have any shared memory needs

15:55 I just need lots of machines to work together

15:55 hiredman: http://vids.myspace.com/index.cfm?fuseaction=vids.individual&videoid=60771080 <-- Origins of APL, the hair styles alone are worth it

16:00 ordnungswidrig: hiredman: great video :-)

16:00 event roger moore has a role in it

16:01 s/nt /n /

16:14 chouser: they seriously didn't pause for a moment when they realized the development of their language required new keyboard mappings, fonts, and a "type ball"?

16:17 ordnungswidrig: chouser: they where from IBM, so it was no issue to build some new hardware.

16:17 chouser: I think

16:18 froog: besides, the world only needed 5-6 computers

16:18 back then

16:18 ordnungswidrig: with a most 640k memory

16:20 the host is smoking while the guest is talking. different times then.

16:20 dublindan: how can i force symbol capture in macros?

16:20 chouser: dublindan: ~'foo

16:20 clojurebot: foo is is Short, Self Contained, Correct (Compilable), Example http://sscce.org/

16:20 dublindan: chouser: thanks!

16:25 javuchi: dysinger: do you have something done?

16:25 dysinger: it's a wip - soon

16:25 I love it :) so simple and so cool :) can't wait to share

16:26 javuchi: would it bring the power of erlang distributed to clojure?

16:27 chouser: javuchi: http://github.com/amitrathore/swarmiji

16:29 javuchi: looks nice, chouser

16:29 dysinger: is your library something like that?

16:29 dysinger: no - that's message queues with no job tracking

16:30 and no peer awareness

16:30 not to knock it - amit is smart

16:30 it's just a different tool than I am targeting

16:31 javuchi: so what are you doing?

16:34 dysinger?

16:37 dysinger: javuchi: above "peer-2-peer work group library in clojure that will allow clusters of repls to work together."

16:38 rhickey: dysinger: are you using something like JGroups under the hood?

16:38 dysinger: IE, not message queues but clustered interacting repls.

16:38 rhickey: yes-ish + branch/leaf node work tracking

16:39 rhickey: cool

16:39 javuchi: dysinger: i'm trying to figure out what exactly you mean

16:39 dysinger: just give me a couple weeks more I'll get it out there O.S.

16:39 danlarkin: dysinger is spilling the secret sauce!

16:39 dysinger: :)

16:40 rhickey: dysinger: thanks for splitting off new branch on build.clojure.org - much easier to see what is what

16:41 dysinger: yeah plus it pollutes the maven repo with mixed branches plus there is a bug in hudson that once you add a branch you can't remove it.

16:41 so it's best to just "copy" the job and modify it for the other branch

16:56 javuchi: what do you think about Shoal?

16:56 (for clustering)

17:01 twbray: Gosh, it turns out that when you have to say -Xmx900m to get a clojure app to run, and it has tons & tons of threads, it really sucks the life out of your basic MacBook.

17:02 hiredman: which one is Xmx again?

17:02 chouser: one of the unsung benefits of single-threaded apps -- no one of them can completely saturate your dual-core machine. :-)

17:03 hiredman: ~google Xmx

17:03 clojurebot: First, out of 66500 results is:

17:03 XMX Home Page

17:03 http://www.cs.brown.edu/software/xmx/

17:03 hiredman: :|

17:03 danlarkin: it's max heap

17:04 hiredman: clojurebot: Xmx is max heap

17:04 clojurebot: Alles klar

17:13 leafw: twbray: if your mac has two cores, try -Xincgc (incremental garbage collector). I found it to make the JVM perform better when creating lots of throwaway objects like clojure does.

17:14 twbray: leafw: Cool, will give it a try. But this thing isn't really designed to run on my laptop :)

17:15 leafw: as for clogging your poor macbook, all one can do is renice the process. Other things help too to avoid swappign: remove window shading, remove window double buffering, closing power hungry apps like MSWord and Photoshop.

17:15 twbray: then ssh to a server :)

17:15 twbray: MSword!?!? Quit talking dirty, this is a respectable IRC channel

17:15 leafw: twbray: I run ubuntu here on a macbook pro 5,5

17:16 twbray: M$word is used by just about everybody I know. And I know it to be a problem, bot memory wise and because it can't be really swapped out; it keeps constant activity

17:17 twbray: leafw: You need to start hanging out with a better crowd :)

17:17 leafw: twbray: the world is larger than you think.

17:21 javuchi: would clojure work with terracotta?

17:21 chouser: javuchi: yes, more or less. There's been some work in that direction, not sure of its current state.

17:29 javuchi: this seems to be the most up to date information?? http://paul.stadig.name/2009/03/clojure-terracotta-next-steps.html

17:31 jbendig: javuchi: Here is someone who uses Clojure with Terracotta on a live system for a vet hospital. http://groups.google.com/group/clojure/browse_thread/thread/85649a134cf22655?tvc=2

17:34 Chousuke: hmmhmm.

17:39 hoh

17:39 Finally managed to compile contrib

17:40 hiredman: :D

17:40 Chousuke: this is a great step forward :P

17:42 hiredman: so even after you could read clojure, contrib still had problems?

17:43 Chousuke: reading is different from reading it correctly so that it can be compiled :P

17:44 hiredman: I mean, you can read clojure.core in and it compiles fine, yes?

17:46 Chousuke: yeah. though I haven't tried to use the compiled result

17:46 ... much :D

17:48 savanni: I asked this before but may have missed the answer, so I'll ask again. Is there a way to enable a stack trace or something for when I get a Null Pointer Exception in my code?

17:49 Chousuke: you can do (.printStackTrace *e)

17:49 if in repl

17:49 * savanni goes to try that

17:49 Chousuke: *e means latest exception

17:51 savanni: Awesome. A little arcane, but that will help out a lot later.

17:51 Chousuke: hmm, contrib tests pass, except for one that overflows the stack for some reason

18:00 hiredman: savanni: checkout clojure.stacktrace

18:03 savanni: Is that in core?

18:03 hiredman: it's in stacktrace.clj, which is right next to core.clj

18:04 savanni: Okay... like with test-is, I'm going to need to upgrade to the clojure dev before I will be able to use it.

18:04 hiredman: are you sure? I'm not sure when it was added

18:05 savanni: Well, my 1.0.0 library claims that clojure.stacktrace is not found, so I would assume so.

18:39 cow-orker: is there a practical difference between #_"comment" and ;comment ? I know they have different "scope", but for short comments...?

18:40 hiredman: #_ eats the following form

18:41 ; drops everything until a newline

18:41 ,#_(

18:41 clojurebot: EOF while reading

18:41 hiredman: ,;(

18:41 clojurebot: EOF while reading

18:41 hiredman: not a good demo, I guess

18:43 cow-orker: well.... I got that part more or less :) I asked because #_"" was used for short comments in (defmacro for ...) in core.clj. Just wondered if there was some reason for commenting that way.

18:43 Chousuke: well, you can put them in the middle of stuff

18:43 ,[foo #_"bar:" bar]

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

18:43 Chousuke: oops

18:43 ,'[foo #_"bar:" bar]

18:43 clojurebot: [foo bar]

18:44 cow-orker: :)

18:44 Chousuke: ,'[foo ;bar: bar]

18:44 clojurebot: EOF while reading

18:48 cow-orker: what got me wondering was in master/src/clj/clojure/core.clj line 3019, but I guess here it's just style

18:50 hiredman: interesting

18:51 I think a lot of that is chouser's work

18:51 (maybe all?)

18:53 cow-orker: thanks, I'll ask him when he's online :)

19:07 Joreji: Hey guys, is there some way to ensure that an agent is running in the main thread?

19:08 rhickey: Joreji: will never be

19:09 they run in thread pools

19:10 Joreji: Oh.

19:10 Ok, thanks.

19:19 How can I translate "new TimerTask() { public void run() { ... } }" into clojure?

19:20 Chousuke: can you construct TimerTasks from callables?

19:21 Joreji: In java? Yes.

19:21 Chousuke: Then you could just do (TimerTask. somefn)

19:21 eg. (TimerTask (fn [] (println "hello"))

19:21 hiredman: no, you can't

19:21 Joreji: But that would require me to write java code.

19:22 hiredman: Joreji: Chousuke meant "Does the TimerTask constructor take a Runnable"

19:22 which it doesn't

19:22 Joreji: Ah, no.

19:22 It does not take a Runnable.

19:22 hiredman: wrapping a fn in a proxied TimerTask is pretty trivial

19:23 Chousuke: I gues you'll need proxy then :)

19:23 +s

19:23 hiredman: I would push you in the direction of ScheduledThreadpoolExecutor

19:23 which takes runnables directly

19:24 Joreji: hiredman: Hm. Are the java timers all running in a different thread?

19:25 onigiri: hi guys

19:26 I'm really really new with clojure, I was playing along with the REPL now and tried some functions:

19:26 I've got a utf8/strings bug (or at least what I think is a bug)

19:26 (.toUpperCase "harajuku 原宿") yields "HARAJUKU 僆宯"

19:27 hiredman: Joreji: Timer uses a single thread

19:28 Joreji: Hm ok.

19:28 onigiri: I'm still trying to wrap my head around functional programming, so I thought that the only thing I was able to do was to report it ;)

19:28 hiredman: onigiri: it might be an issue with java's String

19:28 in which case there is nothing to be done about it

19:29 Chousuke: onigiri: I don't think that's a Clojure bug :)

19:29 onigiri: hiredman: oh ok :)

19:29 Chousuke: amusing, thoug.h

19:29 onigiri: Chousuke: heh

19:30 Chousuke: I guess toUpperCase is just a dumb function that assumes its input is actually something that can sanely be uppercased :P

19:31 onigiri: and the fun thing was that I guess was twbray's fault if I'd tried it :P I remember his talk about unicode and ruby and since he's now learning Clojure, my head mixed the 2 thoughts :P

19:31 Chousuke: yes, I guess so.

19:32 I may peek under the clojure hood to see if there's a hint though

19:32 technomancy: onigiri: there's not much of a hood; that's a direct JVM method call. =)

19:32 twbray: onigiri: That is kind of surprising

19:32 Chousuke: Java strings aren't quite as bad as Ruby (1.8) "strings" but they're not perfect either :/

19:32 twbray: String.toUpper looks at your LOCALE and does all sorts of voodoo

19:33 cemerick: casing is *very* complicated

19:33 onigiri: technomancy: oooh! you're right! I was in fact reading the direct java call

19:33 paragraph...

19:33 twbray: but it should realize that that's in a case-free language and just no-op

19:34 onigiri: twbray: yes, indeed: before asking here I tried with ruby and it worked fine (I tried just to check if I was expecting the correct behaviour)

19:34 twbray: HOld on, I keep a java sandbox project around for just this sort of thing

19:35 cemerick: onigiri: http://www.brosinski.com/stephan/2008/02/09/the-evils-of-javalangstringtouppercase/

19:35 twbray: onigiri: Remember, in my original Ruby/Unicode talk I basically said "Don't use toUpper/toLower". I still think I was right :)

19:35 cemerick: if you provide the target locale, it will likely work correctly

19:36 onigiri: twbray: hehe I know :) I still have that talk burned in my head :)

19:36 cemerick: reading now, thanks

19:37 twbray: onigiri: When I run it in pure Java in NetBeans, it comes out OK

19:39 onigiri: twbray: hmm, if you run in your REPL is the "bug" reproduced?

19:40 twbray: user=> (println (str "In: harajuku 原宿 out: " (. "harajuku 原宿" toUpperCase)))

19:40 In: harajuku 原宿 out: HARAJUKU 原宿

19:40 cemerick: onigiri: what's your system/java locale?

19:40 twbray: Right, try echo $LOCALE at shell

19:41 onigiri: not set

19:42 * twbray looks puzzled

19:42 onigiri: twbray: I'm on a MBP 10.5, and if I run locale, I get LANG="it_IT.UTF-8"

19:43 but an echo $LOCALE yields a deafening void

19:43 twbray: As long as it's got UTF-8 in there you should be OK.

19:43 cemerick: onigiri: eval this in clojure: (java.util.Locale/getDefault)

19:43 onigiri: twbray: you on SLeopard?

19:44 twbray: onigiri: yes

19:44 Java 6, 64 bit

19:44 onigiri: cemerick: hehe here's the culprit

19:44 user=> (java.util.Locale/getDefault)

19:44 #<Locale en_US>

19:44 twbray: onigiri: Same for me, en_US

19:45 cemerick: yeah, that's mine, I don't have an issue with uppercasing those glyphs

19:45 chars*

19:45 twbray: onigiri: What environment are you running in? xterm? IDE?

19:45 onigiri: twbray: plain old Terminal

19:45 twbray: I'm doing this in NetBeans Enclojure REPL

19:46 onigiri: a github cloned clojure just builded

19:46 that was run with a java -jar clojure.jar

19:47 twbray: Hah! When I do it terminal, I see the bug

19:48 Mac Terminal.app I mean

19:48 onigiri: twbray: good, at least I'm not seeing things ;)

19:48 cemerick: funny. Just set your encodings in terminal's prefs, probably

19:49 * twbray looks at Terminal.app's "Encodings" prefs panel, wonders what it means

19:51 twbray: onigiri: Go get enclojure, it's pretty good

19:51 Disabled everything but UTF-8 in the terminal prefs, didn't seem to make any difference.

19:52 onigiri: twbray: I read your post, I was more partial to try the vimclojure

19:52 I don't have any java IDE or emacs installed

19:52 twbray: That might work. Still can't figure out what Terminal.app is sending Clojure though.

19:52 cemerick: twbray: glad you've come around on enclojure :-)

19:53 onigiri: twbray: for what it matters, I tried setting UTF16, but nothing changed

19:53 twbray: oh, of course, inside NetBeans, it's probably an all-UTF16 world.

19:54 cemerick: I presume those are display encodings. It'd be worthwhile to see what code point clojure reports in the terminal for those chars, maybe the input is getting munged.

19:55 twbray: cemerick: I think that has to be it.

19:56 onigiri: Anyhow, the right answer is still the same - don't use toUpper/toLower. (snickers)

19:57 Among other things, they're unbelievable performance pigs.

19:57 onigiri: twbray: hehe

19:58 cemerick: (int (first "宿")) reports 194 in my terminal, 23487 in enclojure, definitely an input issue

19:58 and (count "宿") is 3 :-)

19:58 onigiri: at least this bug made me do a foray in the #irc and now this channel is set for autojoin ;)

19:59 Chousuke: I get 23487 in emacs

19:59 cemerick: ,(.toUpperCase "宿")

19:59 clojurebot: "宿"

19:59 Chousuke: I have it configured to be UTF-8

19:59 cemerick: it's crazy that irc is so unicode-friendly these days

19:59 onigiri: so the Terminal.app is the borked one

20:00 twbray: I usually drop into an aquamacs shell when I have to do serious non-ASCII at the command-line level

20:00 Chousuke: cemerick: well, at least English-speaking people won't have to deal with encoding wars because UTF-8 is ascii-compatible :P

20:00 cemerick: Chousuke: sorry? :-)

20:01 twbray: Maybe iTerm would be better?

20:01 Chousuke: cemerick: some years ago there were debates all over the Finnish IRCSpace whether UTF-8 should be allowed or not, because the de-facto standard was ISO-8859-1 and it's UTF-8-incompatible.

20:02 * onigiri trying iTerm...

20:02 Chousuke: onigiri: I think you need to specify the encoding with a jvm property somehow.

20:03 twbray: Debates about i18n stuff used to regularly provoke paralyzing stupidity up until sometime earlier this decade when everyone just rolled over and gave in to Unicode.

20:03 onigiri: Chousuke: I fear so

20:04 cemerick: Chousuke: I'm guessing it has nothing to do with java.

20:04 Chousuke: I get 194 in iTerm as well, with a plain repl.

20:07 If I do java -Dfile.encoding=UTF-8 -jar clojure.jar then it works. .)

20:07 cemerick: huh

20:08 Chousuke: it defaults to MacRoman on OS X I think

20:09 so when I print UTF-8 in Clojure in an UTF-8 terminal it'll show up even then, but only because the bitpattern happens to match what the terminal expects, not because the JVM prints it out as UTF-8 :)

20:09 onigiri: Chousuke: oh you beat me: I just found the -D flag ;) nice

20:11 so I guess the matter was solved, thanks everyone!

20:11 Chousuke: I wonder why the JVM is MacRoman by default anyway :/

20:11 OS X is pretty much entirely Unicode otherwise :P

20:22 onigiri: ok, back to clojure study

20:53 krumholt: hi can i proxy an abstract class?

20:54 cemerick: yes

20:55 krumholt: so if i proxy something it will be an anonymous class extended from the abstract class?

20:56 cemerick: right

20:56 krumholt: ok thanks

21:01 djork: what's the most idiomatic way to do something n times?

21:01 I've been doing (take n (repeatedly #(foo)))

21:02 but it seems like the closure is a bit unnecessary

21:02 cemerick: dotimes if you're looking for side effects

21:03 mikehinchey: you can just use foo instead of #(foo) if foo is a regular function

21:04 cemerick: hah, I didn't even notice that :-P

21:04 ,(take 5 (repeatedly rand))

21:04 clojurebot: (0.2702439022277704 0.06886273089068606 0.908758027809942 0.5910756151509906 0.9058909510000488)

21:04 cemerick: I wrote that a couple of times last year :-)

21:05 djork: I am looking for dotimes, I think

21:05 cemerick: djork: note that it isn't lazy and returns nil

21:06 djork: not a problem

21:06 just need to literally do something

21:06 purely for side effects

21:06 icey: Anyone here spend much time with compojure? I'm having an issue that doesn't make sense to me when trying to include it in slime. I'm sure it's a noob issue.

21:06 hiredman: what is the issue?

21:07 icey: (I'm getting NoClassDefFoundError on org/apache/commons/fileupload/FileUpload whne I try to (use 'compojure))

21:07 hiredman: ah

21:07 djork: (dotimes [_ 5] (System/gc))

21:07 icey: compojure is in my classpath, I am getting the problem on 2 machines, so whatever I've done wrong I've done wrong in a consistent fashion

21:08 hiredman: just a second

21:08 cemerick: djork: invoking System/gc is generally a waste of time

21:08 hiredman: do you have all of compojures dependencies on the classpath?

21:08 icey: hmm most likely not

21:08 djork: cemerick: not in this case

21:09 it's for a very particular purpose

21:09 hiredman: well, there you go

21:09 if you run ant it will grap a zip of all the deps

21:11 icey: hiredman: i'm taking a look in the deps dir, just so I'm clear all the jars need to go in the classpath? (sorry, I have done like 0 java prior to touching clojure)

21:12 hiredman: yes

21:12 icey: hiredman: i'll give it a swing and see what happens, thanks :D

21:12 hiredman: you can leave out clojure/contrib if you already have those, but you might run into versioning issues

21:29 icey: hiredman: thanks for the tip regarding the classpath stuff on compojure; that did the trick for me :D

21:37 djork: the classpath is a harsh mistress

21:47 anybody using something like this? http://gist.github.com/227662

21:47 is this adequate?

21:47 I use it in my clj script

21:53 _mst: the 1.6 JVM actually lets you do java -cp '/some/where/*' to pick up all .jars from that directory

21:54 but I've used that same trick in 1.5 :)

21:54 djork: oh wow that's nice

21:54 I'm using 1.6

21:54 oh well it's already working

21:54 I can also do . src foo/*.jar to build it

21:54 real globbing is nice

22:56 qed: I know this is kind of a lame question but-- I'm wondering if there are any easier ways than using compojure

22:56 has anyone built an all-in-one installer or package for compojure?

23:08 hiredman: qed: running ant in the git checkout of compojure will download all the dependencies

23:23 * Raynes just got bit by the fact that range's endpoint is non-inclusive.

23:30 qed: hiredman: it's not working for me

23:30 hiredman: what is not working?

23:31 qed: /Users/defn/src/compojure/build.xml:35: /Users/defn/src/compojure/deps not found.

23:31 no deps dir in there

23:31 hiredman: make one?

23:31 qed: omg im a moron

23:31 hiredman:

23:31 qed: apologies

23:32 PS: I didn't need the UTF-8 to rub it in

23:39 technomancy: it would really be great if contrib's 1.0-compat branch got its own version number to distinguish it from master so we could add it to build.clojure.org

23:39 could we bump master up to 1.1.0-alpha-SNAPSHOT to match clojure itself?

Logging service provided by n01se.net