#clojure log - Jan 16 2009

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

0:22 durka: is it possible to define a lazy seq that is reified 100 elements at a time

0:22 i suppose i could just use flatten

0:32 so given that the namespaces a.b.c and a.b.d exist, and a.b.c/f and a.b.d/g are functions in them

0:32 i sort of want to do this

0:33 (use 'a.b)

0:33 (c/f "blah") (d/g "quux")

0:33 but it doesn't work

0:34 is there a way to do that kind of thing?

0:37 Chouser: (require '[a.b.c :as c] '[a.b.d :as d]

0:37 )

0:37 I think.

0:38 or even: (require '(a.b [c :as c] [d :as d]))

0:38 durka: thanks

3:38 sleven: why is it much faster to write to Derby than to postgresql?

4:58 timothypratley: In Rich's ants.clj there is a global 'running', how does this get set to false? [is it ever?]

5:01 hiredman: it would have to be a binding, a set!, or a def

5:01 I have not looked at ants.clj, but maybe running is a flag, and if you set it to false the simulation stops

5:02 timothypratley: http://clojure.googlegroups.com/web/ants.clj

5:02 yeah that's what I thought,

5:02 except it never gets set to false

5:02 hiredman: I imagine you would set it to nil in the repl

5:03 timothypratley: ah :)

12:34 danlarkin: this is a goof, http://kiwi.cabal.fi/home/aki/misc/cons-ceremony.txt

12:41 durka: heh

12:41 bit of a verbose trace there

13:20 Lau_of_DK: Good evening all

13:23 cgrand: evening, Lau!

13:23 durka: good afternoon

13:23 Lau_of_DK: ;)

13:49 clojurebot: svn rev 1216; lift loops from expression contexts

14:03 kefka: I'm using Svn rev 1178. I do not have gen-and-save-class. Do I need a newer version of Clojure?

14:06 danlarkin: kefka: why not update anyway, you'll get lots of bug fixes :)

14:06 hiredman: the gen-and-save stuff is mostly gone

14:06 danlarkin: regarding your question, though, gen-and-save-class is old school

14:06 hiredman: a lot of changes in those areas

14:07 kefka: Ok, so gen-and-save-class is outdated? What do I do if I want to generate a .class file on the fly?

14:07 hiredman: ,(doc compile)

14:07 clojurebot: ------------------------- clojure.core/compile ([lib]) Compiles the namespace named by the symbol lib into a set of classfiles. The source for the lib must be in a proper classpath-relative directory. The output files will go into the directory specified by *compile-path*, and that directory too must be in the classpath.

14:07 hiredman: er

14:08 kefka: you should avoid generating .class files on the fly

14:10 kefka: hiredman: Ok. So what are current best practices for generating a standalone executable?

14:10 hiredman: what are you doing that requires it?

14:10 clojurebot: stand alone?

14:10 clojurebot: Excuse me?

14:10 kefka: I'm sending an executable to a remote machine that has the JVM but not a Clojure intrepreter.

14:10 hiredman: kefka: well, you will need the clojure.jar regardless

14:11 clows: that clojurebot doc just made me realize what i did wrong with gen-class :)

14:11 hiredman: the class clojure generates are just stubs that call to clojure

14:15 clows: if I wanted to subclass a swing class and use that in clojure (and also call methods of that subclass form clojure). would using gen-class allow me do to that?

14:16 Chousuke: gen-class or proxy perhaps

14:16 hiredman: clows: I would look at proxy

14:17 clows: I tried proxy first but i can't seem to be able to access the added methods

14:17 hiredman: proxy does 90% of what people want from gen-class and does it with less fuss and muss

14:17 oh

14:17 yeah

14:17 clows: might be my fault ofc

14:17 hiredman: nah

14:17 proxy doesn't let you add methods

14:17 that is right, for subclassing you still want gen-class

14:17 clows: ok

14:18 hiredman: clojurebot: gen-class?

14:18 clojurebot: No, hiredman, you want gen-interface + proxy

14:18 clows: I'm thinking just doing that stuff in java might be the best way to go anyway ... it kinda gets messy in clojure

14:18 Chousuke: AFAIK if you only need to override superclass methods then proxy works. otherwise you need gen-class

14:19 clows: that'd explain i think

14:20 hiredman: http://clojure.org/compilation <-

14:22 http://gist.github.com/34229 <-- nasty bean maker macros using gen-class

14:23 hmm

14:23 clows: I struggled with gen-class because i didn't have the right classpath ... meh ... but it seems to work now. thats a start :)

14:26 Chousuke: gen-class is a lot easier to use now than it used to be though :P

14:28 clows: it seems easy enough. once you read about *compile-path* ...

14:31 Chouser_: one thing to keep in mind is that lots of stuff that in Java would require a subclass with new methods or data members can be done in Clojure with proxy and closures.

14:32 If you really truly need new methods, then you will have to compile something (gen-class or gen-interface)

14:33 Lau_of_DK: Chouser_: Why isnt your nick verified?

14:33 registered

14:50 pjb3: I'd like to have a ref that contains a vector

14:50 and have some way to call a function like take on it

14:50 where it returns n items from the vector, but also removes them from the vector in the ref

14:51 but obviously in a safe way, so if there are multiple threads pulling stuff from the ref, things don't get taken twice by different threads

14:51 does that make sense? ideas?

14:51 Is there a name for that kind of pattern?

14:52 durka: that's a transaction isn't it

14:53 pjb3: well, it would probably invlove a transaction

14:53 but in thinking about it initially it's tricky because you want to modify what's in the collection

14:54 durka: (doc pop)

14:54 clojurebot: For a list or queue, returns a new list/queue without the first item, for a vector, returns a new vector without the last item. If the collection is empty, throws an exception. Note - not the same as rest/butlast.; arglists ([coll])

14:54 hiredman: pjb3: you want a write lock

14:54 or whatever it is called you you block others from writing

14:54 pjb3: hiredman: yeah, but I thought the whole point of clojure was to avoid having to manage locks :)

14:55 ,(pop '(1 2 3))

14:55 clojurebot: (2 3)

14:55 hiredman: pjb3: depends

14:55 pjb3: see, but I need the 1 as well

14:55 hiredman: (doc peek)

14:55 clojurebot: For a list or queue, same as first, for a vector, same as, but much more efficient than, last. If the collection is empty, returns nil.; arglists ([coll])

14:55 pjb3: ,(peek "xyz")

14:55 clojurebot: java.lang.ClassCastException: java.lang.String cannot be cast to clojure.lang.IPersistentStack

14:55 pjb3: ,(peek [1 2 3])

14:55 clojurebot: 3

14:56 hiredman: ,(peek (seq "xyz"))

14:56 clojurebot: java.lang.ClassCastException: clojure.lang.StringSeq cannot be cast to clojure.lang.IPersistentStack

14:56 hiredman: I see

14:56 pjb3: ,(peek '(1 2 3))

14:56 clojurebot: 1

14:56 hiredman: actually

14:56 yeah, transactions, thats the ticket

14:56 pjb3: What I want is:

14:57 (def stuff (ref '(1 2 3)))

14:57 (take-and-remove 2) => (1 2)

14:57 @stuff => (3)

14:57 hiredman: so if you do the read and write in the same dosync block

14:58 (same transaction)

14:58 pjb3: ,(take 2 '(1 2 3 4 5))

14:58 clojurebot: (1 2)

14:59 pjb3: ,(drop 2 '(1 2 3 4 5))

14:59 clojurebot: (3 4 5)

14:59 pjb3: ah, there it is, do that in a dosync

15:00 hiredman: (doc split-at)

15:00 clojurebot: Returns a vector of [(take n coll) (drop n coll)]; arglists ([n coll])

15:00 pjb3: ,(split-at 2 '(1 2 3 4 5))

15:00 clojurebot: [(1 2) (3 4 5)]

15:01 durka: heh, the source of split-at is its docstring

15:01 Chousuke: :)

15:01 tomsw: Can anyone explain why I get a "method not found" error from java when I try this: (doto (javax.swing.JFrame.)

15:01 (.setLayout (java.awt.GridLayout. 2 2 3 3)))?

15:02 It's from http://en.wikibooks.org/wiki/Clojure_Programming/By_Example - I'm just trying to get the hang of things

15:02 hiredman: tomsw: $5 says you have an old version of clojure

15:02 what is the exact message?

15:03 tomsw: hiredman: java.lang.IllegalArgumentException: No matching method found: .setLayout for class javax.swing.JFrame (NO_SOURCE_FILE:0)

15:04 hiredman: yeah

15:05 you are using the new doto syntax with an old version of clojure

15:05 pjb3: I don't get an error when I run that, just seems to not really do aything

15:05 other than return the JFrame

15:05 oh yeah, that's probably it

15:05 durka: well it won't until you .show the JFrame

15:05 pjb3: (.show *1)

15:05 and there it is :)

15:05 hiredman: you can tell because of the ".setLayout" the fact that it sees the "." in the method name

15:06 tomsw: hiredman: you mean it should be trying to call "setLayout" without the leading dot

15:06 hiredman: yes

15:06 clojurebot: svn?

15:06 clojurebot: svn is http://clojure.googlecode.com/svn/trunk/

15:07 Chousuke: tomsw: download the newer release from google code, or get the latest SVN

15:07 tomsw: hiredman: thanks. I'll install it & pester you all with silly questions in a bit :)

15:07 Chousuke: clojurebot: download

15:07 clojurebot: download is http://code.google.com/p/clojure/downloads/list

15:14 Chouser_: pjb3: you have your transaction function worked out?

15:16 pjb3: Chouser_: Yeah, I haven't written it out yet, but it should just be (let [things (take n the-list)] (drop n the-list) things)

15:16 how do I set the ref to the dropped version of the list?

15:17 hiredman: (doc alter)

15:17 clojurebot: Must be called in a transaction. Sets the in-transaction-value of ref to: (apply fun in-transaction-value-of-ref args) and returns the in-transaction-value of ref.; arglists ([ref fun & args])

15:18 Chouser_: (dosync (let [things (take n the-list)] (alter the-list drop n) things)) I think

15:19 pjb3: (def stuff (ref '(1 2 3 4 5 6 7 8 9)))

15:19 (dosync (alter stuff drop 3))

15:19 java.lang.ClassCastException: clojure.lang.PersistentList

15:19 same for

15:19 (dosync (alter @stuff drop 3))

15:19 Chouser_: ah, indeed. (alter stuff #(drop 3 %))

15:20 durka: (alter stuff (switch drop) 3)

15:20 (defn switch [f] #(f %2 %1))

15:20 Chouser_: heh

15:20 durka: i find myself using that all the time

15:20 Chouser_: really? I just use #(foo arg %)

15:21 pjb3: What's the difference between alter and commute

15:21 ?

15:21 (doc alter)

15:21 clojurebot: Must be called in a transaction. Sets the in-transaction-value of ref to: (apply fun in-transaction-value-of-ref args) and returns the in-transaction-value of ref.; arglists ([ref fun & args])

15:21 pjb3: (doc commute)

15:21 clojurebot: Must be called in a transaction. Sets the in-transaction-value of ref to: (apply fun in-transaction-value-of-ref args) and returns the in-transaction-value of ref. At the commit point of the transaction, sets the value of ref to be: (apply fun most-recently-committed-value-of-ref args) Thus fun should be commutative, or, failing that, you must accept last-one-in-wins behavior. commute allows for more c

15:22 pjb3: I guess commute is faster, so if your operation is communative, you would use that instead of alter?

15:22 clows: java.lang.NoSuchMethodError: clojure.lang.Util.equal ... has that method been renamed by any chance?

15:22 Chouser_: commute is to be used on commutative functions, alter for others

15:23 pjb3: I assume replacing the value of a ref with another value is not communative

15:23 especailly in this case

15:23 so alter is needed

15:23 durka: ,(show clojure.lang.Util)

15:23 clojurebot: java.lang.Exception: Unable to resolve symbol: show in this context

15:23 durka: clows: there is a static equals method, is that it?

15:23 Chouser_: no, alter and commute are always for replacing the value of a ref with another. The difference is the function you pass to each of them.

15:24 I used 'alter' because it's safer. It takes thought to determine if 'commute' will be ok in a given situation.

15:24 pjb3: ,(def x (ref 1))

15:24 clojurebot: DENIED

15:25 clows: dukra: yeah i think so

15:25 I get this error message when trying to (load-file) my test file... java.lang.NoSuchMethodError: clojure.lang.Util.equal(Ljava/lang/Object;Ljava/lang/Object;)Z (internal.clj:26)

15:26 Chouser_: clows: you may need to do a clean and rebuild of clojure, those functions have changed recently.

15:26 pjb3: (def x (ref 1))

15:26 (dosync (alter x inc))

15:26 clows: I thought I did but ... yeah will do again :)

15:26 pjb3: (dosync (commute x inc))

15:26 Chouser_: cleans are supposed to happen automatically now, but someone on the group said that fixed a similar problem for them.

15:27 pjb3: so both of those work, but in that case, you want to use commute, because the operation is communative

15:27 Chouser_: pjb3: the difference will only show up under contention, when two threads are in the transaction at the same time.

15:27 pjb3: I'm not sure I understand how to tell if my function is communative

15:27 Chouser_: for your 'drop' case, i'm pretty sure you need 'alter'

15:27 pjb3: Chouser_: yeah, I agree

15:28 Or would you?

15:28 Because if I have 2 threads that need to get 10 items from the list

15:28 to work on

15:28 they don't care which ones

15:28 durka: if you don't care which one gets in first...

15:28 then it should be commutative

15:28 rhickey: pjb3: you must use alter

15:29 durka: i stand corrected

15:29 what did i miss

15:29 pjb3: The thread doesn't care which items it gets, so shouldn't that be communative?

15:29 Chouser_: with commute, you may see a different value for the ref than will actually be committed.

15:29 rhickey: pjb3: it does care that it doesn't get he same items as another

15:30 pjb3: (dosync (let [items (take 5 stuff)] (comute stuff #(drop 5 %))))

15:30 clows: I think it's a clojure contrib issue (I might have to update that too) :)

15:30 pjb3: that's what we are talking about doing

15:30 Chouser_: In your case if you used commute, the list would always shrink by the right amount, but two threads may get overlapping values, and other may get skipped.

15:30 pjb3: rhickey: that is true

15:30 rhickey: pjb3: that's plainly read-modify-write, must be alter

15:31 pjb3: rhickey: Ok, I'll take your word for it, like you said yesterday, I obviously need to read Java Concurrency in Practice

15:31 rhickey: commute is for things like a tasks-done counter, each transaction wants to increment it, but doesn't care about specific before/after values

15:31 pjb3: so when doing alter

15:31 with the dosync above

15:31 or commute I mean

15:31 in the case above

15:32 if the transaction detects there is a conflict, it won't run the take again?

15:32 rhickey: pjb3: with commute there is never a conflict

15:32 each transaction takes the at-commit time value and modifies it

15:33 you need alter, gotta run...

15:33 pjb3: rhickey: thanks, I believe you, just trying to understand it better

15:34 Chouser_: pjb3: I believe the commutes will get queued up and applied again later.

15:36 pjb3: Chouser_: so what happens with alter?

15:37 Chouser_: with alter, if there's a conflict the whole transaction will be retried.

15:37 I think. :-)

15:37 pjb3: and what does "the whole transaction" mean?

15:37 Chouser_: The outermost enclosing dosync

15:37 pjb3: because I assume that means everything in the body of the dosync, right?

15:38 Chouser_: yes

15:38 pjb3: so if the ref has the numbers 1 - 9 in it

15:38 then thread a starts the dosync from above

15:38 clows: (updating clojure-contrib fixed that btw .... I love it when i trip over my own feet)

15:38 pjb3: first is does take 3 on the ref

15:38 which returns 1 2 3

15:38 then thread b does take 3 on the same ref, also returning 1 2 3

15:39 then thread a does the drop in the alter , which leaves 4 - 9 in the ref

15:39 then thread b tries to do the the drop, which would also leave 4 - 9, but that's a conflict

15:40 so then thread b should restart that dosync, do take 3 which this time returns 4 5 6, because the ref has been altered by thread a to have just 4 - 9 left

15:40 hiredman: in a comute there is no conflict

15:40 pjb3: then thread b does the drop, leaving 7 8 9 and everybody is happy

15:40 hiredman: you are describing alter's behaviour

15:40 Chouser_: pjb3: I think that's right.

15:41 pjb3: thread a got 1 2 3 and thread b got 4 5 6

15:41 hiredman: so what happens differently if I replace alter with commute?

15:41 hiredman: in a comute, the last one in wins

15:41 pjb3: so in the case of commute, if would just blindy do the drop, not checking for conflicts?

15:42 hiredman: there are no conflicts with commute

15:42 pjb3: gotcha

15:42 hiredman: so why would it check?

15:42 pjb3: so a transaction never restarts when there is just commute in there

15:42 I get it now

15:43 so to round out my example from above, if I incorrectly did commute instead of alter, both threads would get 1 2 3

15:43 which is wrong

15:43 and 4 - 9 would be left in the ref

15:43 Chouser_: two threads doing the commute, each dropping 3 would still end up dropping 6 total.

15:44 no, 7-9 would be left in the ref

15:44 the commutes would all happen, just not necessarily in the same order as seen inside the transactions.

15:48 pjb3: Chouser_: ah, you are right, both threads would get 1 2 3, but would each drop, so only 7 8 9 would be left

15:48 so 1 2 3 would get processed twice

15:48 and 4 5 6 never would

15:48 Chouser_: I think that's right.

15:49 pjb3: that;s all assuming the threads actually interleave in that way I described above

15:49 Chouser_: right, it would be a race condition -- sometimes you'd get unwanted results.

15:49 pjb3: this would definitely be one of those nasty concurrency bugs you might not catch until the app is in production

15:49 Chouser_: which is why I use 'alter' until I'm quite sure that 'commute' is ok.

15:49 :-)

15:50 rhickey: pjb3: alter is always correct, so no need to get into commute until you are trying to solve a performance issue

15:50 pjb3: rhickey: good point

15:50 or unless it is a simple counter and you are just using inc

15:51 rhickey: pjb3: there are lots of valid uses of commute, like making an entry in a map

15:51 pjb3: sure

15:51 Chouser_: I wonder if premature optimization is frequently caused by insufficiently interesting problems.

15:51 rhickey: you don't care if someone has added something else in the meantime

15:51 Chouser_: :)

15:51 pjb3: rhickey: you might care if someone has already set a value for that key, right?

15:52 rhickey: pjb3: yes

15:52 more useful for a cache-like thing

15:52 Chouser_: the function you pass to commute will be run twice?

15:53 rhickey: or generated keys

15:53 pjb3: rhickey: you missed it while you were gone, but now I actually understand why I need to use alter :)

15:53 rhickey: Chouser_: yes, twice

15:53 pjb3: great!

15:54 Chouser_: so merge-with might sometimes be a useful option in a commute.

15:59 rhickey: Chouser_: yes, good example

16:12 rfgpfeiffer: Java interop seems to choke on inner classes

16:12 http://gist.github.com/48138

16:16 I don't use inner classes myself, i found this in a paper and wanted to try it out on the REPL

16:16 Chouser_: rfgpfeiffer: the problem is not the inner class but the anonymous package

16:17 I moved R into a package P, and then (.makeAnI (new P.R)) works fine, no import needed.

16:18 rfgpfeiffer: Chouser_: thanks, I will try it

16:26 edw: Hi. My net connection sucks (or will suck once I leave the coffee shop) and I was wondering if there's a nice downloadable set of docs (PDF, HTML tarball, or something similar).

16:27 Chousuke: well, you can always use find-doc and doc in a clojure REPL. Other than that, there's the (non-free) clojure book beta

16:28 Chouser_: there's a PDF of the website, but it may be too out-of-date now to bother with.

16:29 hiredman: you could just print the website to pdf

16:29 Chousuke: though special forms don't have very useful doc strings. All the info of them is on the website

16:29 Chouser_: the html pages have print stylesheets, so yeah, you might try what hiredman said.

16:29 edw: Thanks. I haven't read enough of the docs to know that procedures have documentation.

16:30 Chousuke: (doc find-doc)

16:30 clojurebot: Prints documentation for any var whose documentation or name contains a match for re-string-or-pattern; arglists ([re-string-or-pattern])

16:37 edw: Thanks. I'm making about 40 PDFs right now.

16:38 danlarkin: you can always just download a copy of the website if you want

16:41 pjb3: danlarkin: how do you download a copy of the website?

16:42 * hiredman tries to remember how he generated his pdf copy of the website

16:42 danlarkin: wget can follow links

16:44 hiredman: looks like however I did it already got pushed out of my shell history

16:44 pjb3: danlarkin: Is it really as easy as wget --magic http://clojure.org?

16:44 or do you have to do a bunch of hacking to get a reasonable local copy?

16:46 danlarkin: yeah, wget -m http://clojure.org

16:46 hiredman: I think http://www.easysw.com/htmldoc/ is what I used

16:46 made a pdf of the website

16:47 pjb3: danlarkin: that didn't work, some error about a certificate

16:48 hiredman: actually I guess I used the .org version

16:48 pjb3: wget --no-check-certificate -m http://clojure.org

16:48 that gets past the cert error, but then you only get index.html

16:51 danlarkin: *shrug*

16:51 -m stands for --mirror

16:51 which "Turn on options suitable for mirroring. This option turns on recursion and time-stamping, sets infinite recursion depth and keeps FTP directory listings."

16:51 pjb3: danlarkin: hmmm..well, it don't work :)

17:01 danlarkin: ok, here's an incantation that works for me

17:01 wget --no-check-certificate --mirror -k -w 2 -p clojure.org --convert-links clojure.org

17:02 -p flag probably not necessary

17:09 pjb3: danlarkin: all the links start with /

17:10 Would have to either run it through a web server locally or figure out a way chomp those off

17:11 danlarkin: donno, I'm no wget master

17:11 maybe there's an option for chomping those

17:26 if I'm merging two hash-maps together and I want to remove an element from the first, the appropriate way to do that would be associate it with nil in the second, right?

17:26 ,(:foo (merge {:foo 'bar} {:foo nil}))

17:26 clojurebot: nil

17:26 danlarkin: ,(:foo {:not-foo 'bar})

17:26 clojurebot: nil

17:27 Chouser_: a nil value is not the same as a non-existent entry

17:28 I don't think there's any way to use merge or merge-with and end up with fewer entries than when you started.

17:28 danlarkin: yeahh

17:28 Chouser_: do you have a list of keys you want to remove?

17:28 hiredman: (doc dissoc)

17:28 clojurebot: dissoc[iate]. Returns a new map of the same (hashed/sorted) type, that does not contain a mapping for key(s).; arglists ([map] [map key] [map key & ks])

17:29 danlarkin: Well I want a function to return a hash-map and I'll merge that with another

17:29 but if the function wants to /remove/ an element...

17:29 hiredman: dissoc

17:30 Chouser_: can it return a 2-item vector? [#{set of keys to dissoc} {map to merge}) ?

17:30 danlarkin: Hmm

17:30 hiredman: ,(dissoc {:a 1 :b 2} :a)

17:30 clojurebot: {:b 2}

17:30 danlarkin: Chouser_: yes I suppose it could, although that's uglier :-/

17:30 hiredman: ,(apply dissoc {:a 1 :b 2} #{:a :b})

17:30 clojurebot: {}

17:31 hiredman: danlarkin: why can't the function just dissoc the element it wants to remove?

17:32 Chouser_: danlarkin: if you're sure you never want to have a nil value in your final map, I bet we could write something nice to use nil as a sentinel to mean dissoc

17:32 danlarkin: hiredman: because if I have the function return a hash-map and merge that with another that's no different than just not returning the element from the function

17:33 Chouser_: mmm. yeah it will be allowed nils now that I think about it. I guess I could use :BALLS or something :)

17:34 perhaps I'll just have this function return the entire map and not merge it, even though that's amazing either

17:34 Chouser_: yeah, you could pass in the other map and have the function do the merging.

17:35 danlarkin: yeah

17:37 clows: when i have an anonymous function within an anonymous function *ponder* what does % refer to in that case?

17:38 danlarkin: can't nest #() forms

17:38 clows: ok

18:07 danlarkin: so who's excited for a sweet night of clojure programming?!

18:08 rhickey: I am!

18:08 danlarkin: woo hooo

18:13 grosours: hi there

18:14 rhickey: hi

18:26 stuhood: could coercion and type hinting be combined somehow?

18:26 the coercion example on the wiki is really simple, but it is already an example of coercion being ugly

18:27 from

18:27 (defn foo [n] (loop [i 1] (if (< i n) (recur (inc i)) i)))

18:27 to

18:27 (defn foo2 [n] (let [n (int n)] (loop [i (int 0)] (if (< i n) (recur (inc i)) i))))

18:29 would be nicer to use:

18:29 (defn foo [#^int n] (loop [#^int i 1] (if (< i n) (recur (inc i)) i)))

18:29 dreish: I think having to give extra information to the compiler so it can make your code go faster is always going to be inherently "ugly". That's somewhere way down the list of reasons premature optimization is forbidden.

18:29 hiredman: stuhood: how is that nicer?

18:30 stuhood: it doesn't contain another level of nesting

18:30 for the let

18:30 sp00oon: hey all. was wondering if it was worth my time & money to buy the Stuart Halloway beta book

18:31 dreish: sp00oon: If you're just starting out, I'd say absolutely.

18:40 sp00oon: dreish: Yes. Am just getting my toes wet ;) Thx.

18:42 stuhood: also, it isn't really worth making a ticket about, but 'foo2' at http://clojure.org/java_interop#toc36 won't compile because it contains an extra paren

19:45 LARefugee: Anyone see Charles Nutter's recent talk about the JRuby implementation at InfoQ?

19:58 danlarkin: LARefugee: I haven't, link me?

20:00 LARefugee: danlarkin: http://www.infoq.com/presentations/nutter-jruby-jvm-lang-summit;jsessionid=4F95BB3A93601B4AE6F69BE064CEBEDD

20:00 danlarkin: thanks

20:01 LARefugee: It was gnarly. Ruby is very difficult to make fast.

20:01 On the jvm at least

20:04 dreish: Yet just when you thought no one could invent a slower language, along comes Groovy.

20:06 bitbckt: LARefugee: it isn't particularly quick on C, either. REE is somewhat better, though.

20:08 Charlie likes to puff about JRuby being comparable in speed to Ruby 1.9 and quicker than Ruby 1.8.6

20:08 but that really isn't saying much

20:22 LARefugee: I haven't looked at REE too closely. Besides better memory performance what's the biggest win?

20:25 Ruby's been around since 1993! No decen implementation yet. 1.9 was supposed to be a proof-of-concept on the way to 2.0.

20:27 I was thinking JRuby might be it but after Nutter's talk I'm not so sure people should trust it.

20:40 danlarkin: this talk makes me think JRuby is just like

20:40 not worth it

20:40 with the amount of work arounds they have to do

20:42 LARefugee: danlarkin: I've read Nutter say that the jvm is a good platform for dynamic languages. Sure didn't seem like it, at least not for ruby.

20:44 danlarkin: srsly

20:55 dreish: I think it helps if your language features correspond reasonably closely with what the computer can actually do in a reasonable amount of time.

22:26 LARefugee: clojurebot: logs?

22:26 clojurebot: logs is http://clojure-log.n01se.net/

22:57 Chouser: clojurebot, mind your grammar. "logs are"

22:57 danlarkin: patches welcome

22:57 Chouser: heh

22:57 danlarkin: couldn't resist, haha

23:00 :-o someone actually using clojure-json, sweeeet http://github.com/sethtrain/clojure-github/blob/e27d790078307ecf40840d1c0f9817e03f8e6ea3/src/org/buntin/github/email.clj

23:02 * durka is using it too

23:04 danlarkin: I might change the namespace

23:04 having my name in there bothers me

23:05 durka: i mean, you did write it

23:06 danlarkin: yeah but

23:06 it's lame

23:07 Chouser: danlarkin: have your CA in? You could lobby to have it in contrib.

23:08 danlarkin: true

23:20 durka: goodnight all

23:20 this marks the end of winter break, so we'll see how much time school permits for clojure hacking

23:22 danlarkin: you make your own destiny!

23:44 joshua choi's fnparse is really cool

23:57 now if I could just remember BNF from university

Logging service provided by n01se.net