#clojure log - Nov 08 2009

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

2:52 somnium: (.size (MongoProxy.))

2:52 oops

3:05 stephenj: ~def ->

4:57 ttmrichter: What's the command set for the 'bot here?

5:01 hiredman: clojurebot: how much do you know?

5:01 clojurebot: I know 467 things

5:01 ttmrichter: clojurebot: help

5:01 clojurebot: http://www.khanacademy.org/

5:02 ttmrichter: Ah.

5:02 hiredman: :D

5:02 ttmrichter: And I'm assuming , and ~ are special prefixes?

5:02 hiredman: ~ is equivilant to clojurebot:

5:02 clojurebot: clojurebot is not a benchmarking platform

5:02 ttmrichter: ~ commands

5:02 clojurebot: excusez-moi

5:02 ttmrichter: And the ,?

5:03 ,(add 1 1)

5:03 clojurebot: java.lang.Exception: Unable to resolve symbol: add in this context

5:03 ttmrichter: Oops.

5:03 ,(+ 1 1 )

5:03 clojurebot: 2

5:03 hiredman: actually

5:03 (+ 1 1)

5:03 clojurebot: 2

5:03 ttmrichter: Beat you to it. :D

5:03 hiredman: notice the lack of ,

5:03 ttmrichter: Oh, no I didn't notice that.

5:04 So why is everybody putting , in front (including you)?

5:04 hiredman: (+ 2 3)

5:04 clojurebot: *suffusion of yellow*

5:04 ttmrichter: ,(+ 2 3)

5:04 clojurebot: 5

5:04 ttmrichter: Somebody is an Adams fan, I see.

5:04 (/ 2 3)

5:04 clojurebot: 2/3

5:04 * ttmrichter facepalms.

5:04 ttmrichter: (/ 2.0 3)

5:05 ,(/ 2.0 3)

5:05 clojurebot: 0.6666666666666666

5:05 ttmrichter: ,(/ 2 30)

5:05 clojurebot: 1/15

5:05 ttmrichter: So is there a way to get a full set of instructions for clojurebot?

5:05 hiredman: not so much

5:06 clojurebot: where are you?

5:06 clojurebot: http://github.com/hiredman/clojurebot/tree/master

5:07 hiredman: clojurebot: git 1c8e76b1a0e6616c780902a317a7ab9a8423288b

5:07 clojurebot: newnew is now reify

7:55 spuz: ,(filter seq '("abc" "" "def" "" "ghi"))

7:55 clojurebot: ("abc" "def" "ghi")

7:55 spuz: is that a good way to filter out empty strings from a seqence?

7:57 rhickey: ,(remove empty? ["abc" "" "def" "" "ghi"])

7:57 clojurebot: ("abc" "def" "ghi")

7:57 rhickey: might be clearer

7:57 also, quoted lists are not idiomatic, use vectors

7:58 tomoj: seems like remove empty? is a bit slower for some reason

7:58 rhickey: tomoj: good == clearest or fastest?

7:59 tomoj: in this case the difference in speed is not really significant

7:59 100-200ms on a 100000 element seq

7:59 so, clearest :)

8:00 rhickey: something that is clearer and slower today might be faster tomorrow, but will still be clearer

8:26 spuz: rhickey: thanks

9:00 solussd: is wrapping a function that calls a function that calls alter on a ref in a dosync sufficient to call it in a transaction? I have f2 that needs to run in a transaction, it is called by f1. can i (dosync (f1)) ?

9:01 nevermind- laziness was getting me

9:09 chouser: folding defclass into deftype sounds very pleasant

9:25 gerry`: will there be no defclass only deftype in future?

9:27 rhickey: chouser: ah, good, someone is reading that :)

9:27 yes, I think very doable

9:27 and desirable

9:27 need cemerick to chime in

9:28 cemerick: rhickey: on?

9:28 rhickey: I think the ony gotcha will be people expecting the static aspects to update during dynamic development

9:28 cemerick: http://www.assembla.com/wiki/show/clojure/Datatypes

9:28 folding defclass into deftype, i.e. you get named class when AOT compiling deftype

9:28 under: New ideas/scratchpad

9:29 gerry`: it seems cool

9:29 rhickey: for instance if you change the deftype and call new, you'll still get the AOT-compiled version

9:30 and (.field calls) will fail on non-AOT based instances

9:31 gerry`: but if i really want a changed AOT class?

9:31 rhickey: OTOH, if (:field x) is as fast as (.field x) (at least for non-polymorphic sites), then why use (.field x)

9:31 gerry`: compile again

9:31 and restart :(

9:32 djpowell: what is :field using now? is it not using case any more?

9:32 rhickey: djpowell: it is backed by case, but there is not per-call-site caching of (:field x) calls

9:33 in my tests, when the type of x doesn't change at a callsite, the perf is identical to (.field x)

9:33 and of course, in real code using (.field x) the type of x isn't changing

9:34 djpowell: is the call site caching stuff described anywhere - i saw some checkins, but I didn't understand it

9:34 rhickey: cemerick: did you change all of your defstructs to defclasses or deftypes? and if the latter, to (.field x). If so maybe you could see if there is any perf disadvantage for you using (;field x)

9:35 djpowell: I just tried to describe it to some people the other day, in person, with diagrams, took over an hour

9:36 gerry`: rhickey: your new ideas/scatchpad should be put at top of wiki page

9:37 rhickey: gerry`: I don't want people to get confused by speculation, the top is now working documentation for working code

9:38 cemerick: rhickey: they all got replaced by defclass; they're implementing public named interfaces

9:38 rhickey: cemerick: oh, that's right

9:38 so you are not as good a test case then

9:38 for deftype

9:39 cemerick: yeah, we're using it in only limited circumstances -- really, only where we'd otherwise be using regular maps with a stable set of slots

9:40 I'm all for simplification though: right now, we have deftype, defclass, gen-class, proxy, and reify, which is quite a buffet to choose from if you're new.

9:42 rhickey: so, other than user confusion about the lack of dynamicity of named things (a recurring problem), the only real sticking point is the clash between the factory fn name and the class name

9:43 seems a shame that people using Java can get (Foo. 1 2 3) where people using deftype dynamically will get (make-Foo 1 2 3) or something

9:43 but my.ns.Foo can't name both the class and the facgory

9:43 factory

9:44 well, could but shouldn't

9:52 avital: Hello. I just started using Emacs/Slime with a remote Swank server and it keeps disconnecting. It may be something with my internet connection but I just wanted to check if anyone experiences similar issues...

10:00 cemerick: rhickey: w.r.t. "calls to (new Foo ...) will still use compiled class" -- perhaps the compiler should emit some hairy warning when loading a deftype is already defined in a compiled class?

10:02 rhickey: cemerick: If people aren't calling new or .field in Clojure code, i.e. using the factory fn and :field, then reloading a non-problem

10:03 static name could just be for Java consumers

10:04 or serialization, that was a use case of yours, any thoughts?

10:04 cemerick: rhickey: true, but if you're not calling new or using .field, then there's no reason to be AOT compiling, either.

10:04 or, AOT compiling with any potential of reloading, I should say

10:05 rhickey: cemerick: not sure I get that, if I AOT for consumption by JAva, no harm/no foul if I reload during dev

10:06 I just don't see it as a clear error

10:07 cemerick: OK, I'm reading "will still use compiled class" as meaning reloading will be a no-op for sites using new. Not an error, perhaps, but pretty darn surprising, I'd say.

10:08 rhickey: cemerick: why use (.field x) or new from Clojure code?

10:09 note calls to new inside methods will work properly, as will naked local field refs: field

10:10 cemerick: hrm, OK. In that case, I withdraw. :-)

10:10 rhickey: the point of factory fns and fast (:field x) is to get people away from marrying AOT-static things

10:11 note that I don't disagree - the behavior of new and .field may be both surprising and disappointing upon reload

10:12 I get tired of explaining the static nature of Java classes and the problems with having/eating cake

10:13 deftypes + protocols should provide a high-performance dynamic alternative, with good bridges

10:13 cemerick: Right. Well, that's largely why I suggested the warning, but the need for it depends a lot on how closely people will hew to idiomatic usage of the classes generated by deftype/class.

10:14 i.e. :field rather than .field

10:14 rhickey: cemerick: I think the story has to be that new and .field are for interop consumption on the Java side

10:16 djpowell: if you are using new and .field for interop on the Java side, then having to recompile probably isn't too surprising

10:16 rhickey: djpowell: exactly

10:19 djpowell: so... what code do you have to write in clojure for the call site caching stuff to kick in? is it keyword based access?

10:21 rhickey: keyword callsites design diagram: http://www.assembla.com/spaces/clojure/documents/download/keywordcallsites.pdf

10:21 djpowell: ok cool i'll take a look

10:21 rhickey: djpowell: just (:k x) where x is a deftype/class instance

10:22 that diagram is not meant to be self-explanatory :), just what I had at hand

10:26 Chousuke: Hopefully the JVM will be smart enough to optimise away most of the (identical? ret ...) checks, too.

10:28 though I suppose it'll have to have a check *somewhere*.

10:28 rhickey: Chousuke: yes, the fastpath presumes false, pipelining makes it 'free'

10:29 the truly amazing thing is that hotspot can dynamically lift the thunk 'get' body inline into the host method

10:29 Chousuke: That's kind of counterintuitive, but nice nonetherless.

10:29 -r

10:30 Just goes to show that common sense assumptions about fast code hold less and less as processors and virtual machines advance :/

10:31 * rhickey practices omnigraffle-driven-design. hrm, that's ODD

10:37 Chousuke: "Is the chart readable? no? Redesign."

13:03 chouser: We just need alternate punctuation for the factory fn, vs the trailing . for 'new'.

13:08 So (new Foo x) or (Foo. x) for java interop, (new-Foo x) or (Foo< x) for deftype

13:14 Chousuke: I suppose Foo: would be too easy to typo :P

13:14 chouser: but much prettier than Foo<

13:15 Chousuke: if Foo weren't capitalised I'd just suggest make-* but make-Foo is kind of icky.

13:18 mikehinchey: I don't think make-Foo is that bad, and more clear than a special char

13:20 chouser: google search is now apparently crawling the clojure-log every few hours now

13:22 hiredman: special

13:28 solussd: it's been doing that for awhile. :)

13:29 hiredman: clojurebot: fun with vars is <reply>http://www.slideshare.net/mudphone/fun-with-vars

13:29 clojurebot: Roger.

14:43 djork: would it be possible to build a lazy seq using StringTokenizer?

14:43 I can do it all in one shot

14:44 with loop

14:44 chouser: sure could

14:44 using lazy-seq directly is probably the most straightforward

14:44 djork: lazy-seq doesn't use any stack space?

14:45 when evaluated?

14:45 chouser: a function that uses lazy-seq correclty and idiomatically will not consume stack space.

14:45 djork: ok

14:47 chouser: "StringTokenizer is a legacy class that is retained for compatibility reasons although its use is discouraged in new code."

14:48 djork: oh, that too I guess :)

14:48 chouser: you could produce a lazy seq from StreamTokenizer as well, though you'd have to be careful about getting the InputStream or Reader closed correctly.

14:49 djork: yeah

14:54 I'm looking at things like re-partition from clojure.contrib.str-utils

14:54 it seems like it would consume stack space

14:56 I see a pattern like (fn foo [] (lazy-seq (cons bar (foo))))

14:56 where foo is most definitely not in tail position... but is that not an issue with lazy-seq?

14:59 chouser: lazy-seq is a macro -- the expression inside it is put into a closure and returned

15:00 do you know how trampolines work, either in Clojure or other languages?

15:01 porpoise: Can someone help me with getting clojure to work with swank and jswat? I have it working with swank/Emacs but can't get it to open a port of external debugging

15:02 Bill Clementson's site describes how to do it, but it's completely different from the automatic set up that was recommended to me as the current way to install it

15:02 lisppaste8: froog pasted "with-open and *out*, is this the way to do it?" at http://paste.lisp.org/display/90001

15:03 djork: chouser: nope, not familiar with trampoline

15:03 http://gist.github.com/229461

15:03 chouser: froog: looks good to me

15:04 djork: damn, trampoline means about 20 different things :) http://en.wikipedia.org/wiki/Trampoline_(computers)

15:05 porpoise: What's the recommended way to install clojure with swank, and enable Jswat?

15:05 chouser: djork: don't worry about trampolines -- if you already were familier I could use that to explain lazy-seq.

15:05 djork: oh ok

15:06 chouser: djork: your gist is close, but the body of the lazy-seq needs to always return a seq (or nil), not a string

15:06 djork: next-tok will be nil in the false case of that if

15:06 bad style, probably

15:06 froog: chouser: I wish the extra binding wasn't necessary, but I guess there's great wisdom behind the different 'let' and 'binding'

15:06 chouser: djork: oh! sorry, let me read again.

15:07 djork: there has to be an idiomatic way to express (if foo bar nil)

15:07 chouser: djork: (when foo bar)

15:07 djork: excellent

15:07 you know I was reading some article that said "Clojure doesn't have a faq, it has chouser"

15:08 chouser: heh

15:08 djork: you need a break man

15:08 clojure.contrib.chouser-vacation-fund

15:09 chouser: Speaking of which, I'm off to read Narnia to the kids. Good luck, all.

15:09 djork: edited: http://gist.github.com/229461

15:10 chouser: djork: perfect, though I might recommend the name 'step' instead of 'next'

15:11 djork: yes, now go be an awesome dad

15:58 turbo24prg: morning

18:44 skybound_: i was wondering if i might suggest a small fix for repl_utils.clj; (source load-file) throws an NPE, as the symbol doesn't have a :file meta entry and .getResourceAsStream doesn't appreciate nil. i realize this isn't a critical kind of bug...

19:19 chouser: skybound_: fixed, thanks.

19:25 skybound_: chouser: you are welcome; and thanks for fixing, i wouldn't want to send in a contrib-agreement for such a small patch.

19:31 i think this would be nice to have for java code as well, but for the moment i don't see an easy way to do it

19:32 chouser: you mean for Clojure's own .java files?

19:33 they're not usually in the .jar or on the classpath, so the files would be a bit tricky to find in the first place.

19:33 skybound_: no, i mean for any kind of java/class files where both are available to the classloader; like my own legacy java libs

19:34 chouser: oh, you have .java files in the classpath? I'm not a Java guy -- is that common?

19:34 you can use 'show' to do some examination of the Java classes themselves.

19:35 maybe not the best chosen names. :-/

19:38 skybound_: it depends i guess, during dev i usually package source into the jars. for the moment my main usage of clojure is poking around in a java app via the repl.

19:39 the idea is probably not worth the effort

19:41 chouser: when tracking down a Clojure behavior I often start with 'source' at the repl, but as I walk down the function calls end up at a java interop form, at which point I have to load the .java in an editor which is an unfortunate transition.

19:45 skybound_: right

20:48 littleidea: Learning clojure, philosophical question, when do you choose (. class-or-instance method-name args) or

20:48 (.method-name class-or-instance args)? Is it just style or is there ever a clear preference for one over the other?

20:48 hiredman: .method-name is the prefered idiom

20:50 littleidea: ok, thanks, that seems closer to the CLOS idiom

20:51 hiredman: even before .method-name existed I think (. class-or-instance (method-name args)) was prefered over (. class-or-instance method-name args)

20:52 chouser: (. i m (a)) is the oldest -- we've gotten steadily better since then. :-)

20:52 er, (. i (m a))

20:52 hiredman: chouser: oh

20:52 chouser: I think. I could be remembering wrong. anyway, don't use either one.

20:52 littleidea: gotcha

20:53 chouser: unless you're generating them in a macro. Sometimes they're a bit more convenient there.

20:54 hiredman: because .foo is taken care of by the reader, and once you are in macro land you don't have the reader holding your hand

21:19 chouser: not quite

21:19 ,(read-string "(.foo bar)")

21:19 clojurebot: (.foo bar)

21:19 chouser: ,(first (read-string "(.foo bar)"))

21:19 clojurebot: .foo

21:19 hiredman: huh

21:19 chouser: it's actually expanded during macro-expand time, so you *can* use that form in a macro, it's just annoying.

21:20 ,(macroexpand (list '.foo 'bar))

21:20 clojurebot: (. bar foo)

21:21 * hiredman misrembers some more in an attempt to clear the faulty data

21:23 chouser: ,(macroexpand (let [method 'foo] `(. bar ~method)))

21:23 clojurebot: (. sandbox/bar foo)

21:24 chouser: ^^ simple

21:24 (macroexpand (let [method 'foo] `(~(symbol (str "." method)) bar)))

21:24 ,(macroexpand (let [method 'foo] `(~(symbol (str "." method)) bar)))

21:24 clojurebot: (. sandbox/bar foo)

21:24 chouser: ^^ annoying

21:59 hiredman: does *your* reader expand them? :-)

22:00 hiredman: nope

22:01 I think I was misrembering the part where the reader turns symbols naming classes into Class objects

22:20 st3fan: i see parenthesis when i close my eyes

22:20 too much code

22:20 totally sarting to like clojure

22:28 is there a shortcut for (filter #(not (nil? %)) c) ?

22:29 timothypratley2: I think (remove nil? c) from memory

22:30 ,(remove nil? [1 2 nil 3])

22:30 clojurebot: (1 2 3)

22:34 hiredman: ,(filter identity [1 2 nil 3 4])

22:34 clojurebot: (1 2 3 4)

22:34 plunket: ,(loop infinite)

22:34 clojurebot: java.lang.IllegalArgumentException: loop requires a vector for its binding

22:34 st3fan: cool

22:34 hiredman: ,(filter (comp not nil?) [1 2 nil 3 4])

22:34 clojurebot: (1 2 3 4)

22:34 plunket: ,(loop (print "hello))

22:34 clojurebot: EOF while reading string

22:34 plunket: ,(loop (print "hello"))

22:34 clojurebot: java.lang.IllegalArgumentException: loop requires a vector for its binding

22:35 st3fan: even better would be a map function that would only return non-nil items

22:35 plunket: ,(loop [print "hello"])

22:35 clojurebot: nil

22:35 hiredman: ,(filter (complement nil?) [1 2 nil 3 4])

22:35 clojurebot: (1 2 3 4)

22:35 plunket: ,(loop [5])

22:35 clojurebot: java.lang.IllegalArgumentException: loop requires an even number of forms in binding vector

22:35 plunket: ,(loop [5 8])

22:35 clojurebot: java.lang.Exception: Unsupported binding form: 5

22:43 wtetzner|nyx: ,(loop [x 10] (if (zero? x) (println "done.") (do (println (str "x = " x)) (recur (dec x)))))

22:43 clojurebot: x = 10 x = 9 x = 8 x = 7 x = 6 x = 5 x = 4 x = 3 x = 2 x = 1 done.

22:45 st3fan: can anyone give me an example of if-let ?

22:45 timothypratley2: ,(if-let [a true] 10)

22:45 clojurebot: 10

22:45 wtetzner|nyx: ,(if-let [a false] 10)

22:45 clojurebot: nil

22:46 st3fan: oh so it is simply if the binding evaluates to a true value then the body is executed

22:46 timothypratley2: yup

22:46 wtetzner|nyx: it only executes what's in the if-let if the binding is non-nil and non-false

22:46 st3fan: ok

23:03 hm too bad if-let doesn't support multiple bindings .. would be nice if it would try all bindings and exec the body if they all returned a non-nil value

Logging service provided by n01se.net