#clojure log - Jul 03 2008

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

0:13 slava: Chouser: in the jvm, a 'try' block has zero cost if no exception is thrown

0:13 Chouser: slava: cool, thanks!

0:14 slava: i assume clojure compiles to intelligent bytecode for exception handling, then it won't be a performance issue at all

3:27 hoeck: cgrand: tried cryoPID on a clojured jvm, it somehow suspends and awakes, but it seems to close all file descriptors (at least the cryopid i built on my machine)

3:43 cgrand: hoeck: wow, I was kidding :-) Btw, I tried it myself yesterday and I ran into 2 pbs, one can easily be fixed (unlinking the file where hotspot stores runtime statistics so as to have cryopid embed this file in the snapshot), and the other one requires more work: cryopid works only on single threaded processes :-(

4:27 hoeck: cgrand: i was curious about that, it would be nice to suspend the jvm under certain conditions, but as my 'sessions' mostly include swing frames, it wouldn't be of great use for me.

4:36 cgrand: hoeck: there's other checkpointing solutions: https://lists.linux-foundation.org/pipermail/clusters_sig/attachments/20051025/88ed8b30/Comparison-CR-0001.pdf but restoring a swing app is certainly tricky

4:42 hoeck: i'm wondering that there is no suspend capability built into the jvm, that should be easier than suspending the whole jvm process

4:45 BTW, i've got a laptop with working acpi-suspend-to-ram, so i can at least save one single clojure session :)

4:46 cgrand: :-)

5:37 Ycros: hoeck: if you're on linux you could try http://cryopid.berlios.de/

6:15 hoeck: ycros: yeah, cgrand already suggested it, and i tried it too, but it didn't work properly on my machine

10:16 * rhickey_ added drop-last

10:18 cemerick: anyone planning to go to oopsla?

10:21 * pjb3 has no idea what oopsla is

10:22 * pjb3 has learned through the magic of google that oopsla is a conference on Object-Oriented Programming, Systems, Languages, and Applications

10:22 Chouser_: rhickey_: I'm in awe of drop-last's implementation. And thanks, I need it for lazy-xml.

10:33 If s is not itself a sequence, (seq s) will create a cache for the results as it walks along, right? Then won't the call to seq inside (drop n s) create its own separate cache?

10:37 rhickey_: a seq is a cursor, there isn't a lingering cache unless the interim seqs are held, but it will create 2 cursors unless you pass it a seq

10:38 I can add a (let [s (seq s)] ...

10:39 Chouser_: right, I was just trying to figure out if that would help anything or not

10:41 seems like it wouldn't really. You'd mainly want to make sure that if computing (rest s) takes any real work that it doesn't do it again just to track the offset. But if s was built with (lazy-cons) both calls to (seq) will just point to the original, so there wouldn't be a problem.

10:41 rhickey_: not if it's already a seq, then the drop seq is creating cache that the head will reuse

10:42 Chouser_: right

10:43 which leaves things like maps and vectors, where I assume advancing a seq is pretty lightweight.

10:43 rhickey_: Chouser_: yes, and you don't ever lose the advancing cost

10:44 Chouser_: and wouldn't be cached anyway ... right, ok.

10:45 rhickey_: one advantage of 2 cursors is you won't be holding onto n seqs in the interval, _unless_ you were passed a seq in the first place

10:49 Chouser_: I wrote a lazy-but-last a couple days ago and thought briefly about how much more code it would take to handle n>1; I was nowhere close to your implementation.

10:56 rhickey_: Chouser_: I constantly have to remind myself to try to use a higher-order fn, because lazy-cons is so easy

10:57 Chouser_: yeah, mine used destructuring to look ahead and lazy-cons to build the result. I thought I was all clever.

11:01 rhickey_: Chouser_: cgrand had the right idea earlier this week, just did work map already does: http://clj-me.blogspot.com/2008/07/lazy-butlast.html

11:04 Chouser_: I saw your case - one of the things Lisp cases do is take multiple test values that match to a single expr

11:07 Chouser_: I hadn't seen cgrand's blog. He did a lazy-in-another-thread too.

11:10 rhickey_: Chouser_: yeah, it's a one-ahead IIRC. I didn't see the need to go to Executors/Futures rather than use agents

11:11 Chouser_: yep, one-ahead. But it's interesting to me that he, I, and abrooks apparently all started thinking about that basic idea within the last week or so.

11:36 cemerick: rhickey_: Are there any plans to support overloads with the same arity but different signatures? (e.g. (defn foo ([#^String a] a) ([#^Integer a] a))

11:36 rhickey_: cemerick: no

11:36 multimethods?

11:37 cemerick: I'm thinking about that only in connection with proxy / gen-class.

11:37 rhickey_: proxy routes to a single handler, but gen-class can do that now

11:38 cemerick: right, right, param-types.

11:40 rhickey_: then independent handlers foo-String, foo-int

11:40 hmm... looks like that feature is not documented

12:31 lisppaste8: ?

12:32 Chouser_: rhickey_: are you opposed to an :else in case? Seems like it would be handy if the keyform is complex.

12:33 rhickey_: what if the keyform is :else ?

12:33 Chouser_: [:else]

12:33 same if you need to match a vector

12:33 rhickey_: what if the keyform is [:else] ?

12:34 Chouser_: [[:else]]

12:34 [1 2 3] will match 1 or 2 or 3

12:34 rhickey_: are you always requiring [] ?

12:35 Chouser_: no, any non-vector gets one vector wrapped around it

12:35 [[1 2 3] 4] will match [1 2 3] or 4

12:36 rhickey_: :a becomes [:a] in the expansion?

12:36 Chouser_: [:a :else 5] matches :a, :else, or 5; [:else] matches just [:else]; :else matches everything

12:37 [:a] and :a both become (or (= key :a))

12:38 rhickey_: hmm... maybe lists for grouping?

12:38 Chouser_: I guess requiring [] wouldn't hurt too bad, but I think not requiring it will be more helpful than confusing. I dunno, maybe I've got that backwards.

12:39 well, right now I'm evalling the keys so non-constants are allowed, so lists would require quoting.

12:40 rhickey_: most cases don't allow non-constants

12:40 Chouser_: between that and the fact that [] are visually different from the likely () used in the result expressions led me to use vectors.

12:41 lisppaste8: rhickey pasted "seque redux" at http://paste.lisp.org/display/63224

12:43 Chouser_: ah, sure

12:45 rhickey_: Chouser_: I'm not sure more configurability than pluggable queue is needed

12:46 Chouser_: ok

12:50 I figured out a way to put a finally clause back instead of catching and re-throwing the exception, but it only saves one line of code and puts the try block inside the loop. I didn't know if that was really better or not.

12:51 rhickey_: exception only has overhead when you have one, in which case efficiency isn't your problem :)

12:53 Thanks for your input on this. If no one sees any obvious deficiencies, I'll add that seque to Clojure

12:54 Chouser_: you're welcome, it's been fun.

12:55 I might yet take one more swing at a configurable fill to allow me my ugly *enqueue* thing. Maybe SAX parsers are the only thing that will ever need it, but I just wouldn't be surprised if some other Java interop could use it.

12:58 lisppaste8: Chouser annotated #63224 with "finally instead of catch/throw (if it matters)" at http://paste.lisp.org/display/63224#1

13:00 Chouser_: no, don't use that. If .offer throws something we'll be in bad shape

13:02 Lau_of_DK: Evening Gents

13:11 StartsWithK: Why do examples of gen-and-save-class (http://paste.lisp.org/display/63177 http://is.gd/Ljy) use (clojure/refere 'clojure) but when i do it i get a error saying that defs from clojure are allready in my ns http://pastebin.com/d3d640c0b

13:11 i tried, but its just insane to prefix everything with clojure/

13:18 Lau_of_DK: I think its due to your initial (in-ns) , but its just a hunch

13:18 does that ns refer clojure?

13:18 Chouser_: StartsWithK: yeah, you can also try using :exclude or :only in your (refer), but that also gets a bit painful.

13:19 StartsWithK: Lau_of_DK, how else will i implement functions that will map to class methods?

13:19 Chouser_: rhickey outlined a solution but I don't think he's started work on it yet.

13:19 Lau_of_DK: Does (com.paulbarry.HelloWorldServlet) refer Clojure ?

13:19 StartsWithK: Chouser, but ill have to exclude every function i use

13:20 and not only that, but ill have to do it in every .clj file i have

13:20 not only in that one..

13:22 Chouser_: well, just in your com.paulbarry.HelloWorldServlet ns, you would say (clojure/refer 'clojure :exclude '(print)) and such

13:22 you might have several more besides print, but you'd only need to do it in genclass namespaces, not all your other ones.

13:23 StartsWithK: but i then use (clojure/refer 'gl) or any other ns i have, and i get the same error for that file..

13:24 i wouldn't like to put that :exclude in every file ill use

13:25 Chouser_: is 'gl a genclass namespace?

13:25 StartsWithK: no

13:25 Chouser_: but it defines a print function?

13:26 StartsWithK: no

13:26 but it starts with (cojure/in-ns 'gl) (clojure/refer 'clojure)

13:27 Chouser_: and that gives you an error? what name is conflicting between 'gl and 'clojure?

13:28 StartsWithK: print

13:29 but i guess thats just first conflict it finds so it stops there

13:30 Chouser_: ok, I'm still missing something. 'clojure defines print. if you have a conflict on (refer 'clojure) in 'gl, then 'gl must define print, either manually or via genclass

13:30 maybe you can paste a small standalone example of the failure?

13:36 StartsWithK: http://freehg.org/u/kresimir/neman/file/73d324443f70/ in examples directory is GearsApplet.clj and in neman subdirectory there is a gl.clj, error i get is http://pastebin.com/d3d640c0b

13:39 rhickey_: gen-class is going to create vars in your ns for _every_ non-private method in all superclasses/interfaces, so if one of your superclasses has print, that's all it takes

13:39 looks like java.awt.Container has print

13:41 StartsWithK: so ill have to exclude everything that some superclass implements when refering to clojure namespace?

13:41 rhickey_: or :only the things you use in the refer call, at least until I change this

14:13 * rhickey added seque

14:23 * Chouser_ rebuilds

14:41 cemerick: rhickey: any reason why delay is private?

14:43 rhickey: cemerick: I don't want to promise its continued existence - was an implementation helper at one point

14:46 Chouser_: hashes seem to return int keys in sorted order.

14:47 cemerick: it, or something similar is pretty necessary, IMO. A lazy companion is worthwhile, too (thinking here of the plt promise lib).

14:49 I've got a delay-fn macro around here somewhere that expands into a delay that can take arguments, which can be handy.

14:53 rhickey_: I'm not opposed, I just don't want people reinventing lazy seqs...

14:54 when I first released Clojure I had to spend a lot of time explaining how and why it was different from Scheme

14:55 cemerick: isn't delay inherently lazy?

14:56 cemerick: rhickey_: Ah, no, I mean a function named "lazy" (or something like the scheme function of the same name). i.e. http://docs.plt-scheme.org/reference/Delayed_Evaluation.html

14:57 I never liked the 'force' mechanic -- simply evaluating the thunk provided by delay or lazy always seemed more reasonable to me.

14:57 rhickey_: That's what delay does, just that it supports IFn, so the way to force it is to call it

14:57 cemerick: exactly -- much better 'usability', IMO

14:58 I'm surprised you fielded questions about clojure w.r.t. scheme similarities/differences. There's plenty of variation out there, already.

14:59 rhickey_: (import '(clojure.lang Delay))

14:59 (def p (Delay. #(println "Hello")))

14:59 (p)

14:59 (p)

15:00 no TCO is the big difference from Scheme

15:00 cemerick: Yeah, I could do that. I'm using my own delay macro until I know clojure.lang.Delay is sticking around. :-)

15:00 rhickey_: many other superficial differences

15:01 cemerick: what does you delay macro use?

15:01 your

15:01 cemerick: Feh. (almost) pointless academic pissing matches, IMO.

15:11 Lau_of_DK: rhickey_: Isnt it about time, that you make (time ) produce some nicer output?

15:21 Chouser_: ah, such fun: (defn perm [r m p] (if (> m 0) (mapcat #(perm (disj r %) (dec m) (conj p %)) r) [p]))

15:22 (perm #{0 1 2} 3 []) => ([0 1 2] [0 2 1] [1 0 2] [1 2 0] [2 0 1] [2 1 0])

15:23 rhickey_: neart

15:23 neat

15:25 Chouser_: I can generate a million permutations of 10 digits in about 11 seconds.

15:26 rhickey_: cool

15:27 where's lazy-perm?

15:27 :)

15:27 Chouser_: hmph

15:28 I'll write it as soon as I can find lazy-mapcat in boot.clj

15:28 rhickey_: do you need that? won't it be lazy-cat .. map ...

15:29 Chouser_: hm, dunno, I just spoke without really thinking. hardly ever happens. ;-)

15:29 that is lazy, isn't it?

15:30 yeah, it is. I wrote lazy-perm already. leave me alone. I've got a database to resintall...

15:30 and a C++ app to recompile

15:33 lisppaste8: Chouser annotated #63135 with "case with vectors and :else" at http://paste.lisp.org/display/63135#1

15:37 cemerick: rhickey_: my delay macro isn't anything special. It just takes a function body, and then keeps a map in a ref that holds the thunk, and then the "forced" value after the fn that the macro generates is evaled.

15:38 rhickey_: how does it know it's been forced?

15:38 cemerick: It checks the map in the ref for a value in a :result slot.

15:39 I have a "fancier" one that will accept arguments on the "force", but then it's a little weird in that it'll return the same forced value for any arguments provided afterwards. I thought it was such a good idea, until I didn't. ;-)

15:41 rhickey_: if your thunk has side effects or takes a long time, might be incompatible with the transaction running multiple times

15:42 cemerick: Yeah, it has the same dynamics as memoize (I think).

15:43 I don't double-check the ref's map (like you double-check around the synchronize in clojure.lang.Delay), but it Works For Me (tm).

15:43 I suppose I could add that *shrug*

15:44 rhickey_: if the delayed expression has side effects you can't use transactions for this

15:46 lisppaste8: cemerick pasted "delay macro" at http://paste.lisp.org/display/63238

15:46 Chouser_: shouldn't use anything with side effects in a transaction, right? Actually, I should stop talking, since I've been staring at the implementation of Delay and still don't get it.

15:47 cemerick: well, if you're trying to delay something you know has side effects, and you know you want those side effects to apply on every access of that delayed expression, then you're not using delay properly, right?

15:47 by that I mean, all delay mechanisms have this problem, no?

15:48 s/problem/"problem"

15:48 rhickey_: no, delay is run once, cache result

15:48 Chouser_: oh!

15:48 cemerick: ok

15:49 * cemerick worries that he's getting stupider every time rhickey_ talks ;-)

15:49 rhickey_: cemerick: this stuff is tricky

15:50 the macro has a few problems independent of the semantics of delay. You are doing several 'flying reads', i.e. outside the transaction, of values that matter to you in the transaction. Those reads should be in the transaction

15:51 cemerick: rhickey_: Yeah, I know. I just knocked it out last night when I saw that boot.clj's delay wasn't open for business.

15:52 I wanted to check with you on its status/future before bullet-proofing it.

15:52 "it" referring to two different things there, of course...

15:53 rhickey_: are you concerned in general about people wandering into using delay inappropriately, etc?

15:53 * rhickey_ is documenting and making delay public

15:54 * cemerick is saved from himself, yet again

16:08 * rhickey_ added delay

16:08 rhickey_: I made it so the resulting object implements both IFn and IRef, so you can 'force/read' it with either (x) or @x

16:09 cemerick: ooooh, shiny :-)

16:10 Chouser_: like memoizing a function with no args

16:11 lisppaste8: cemerick annotated #63238 with "fixes to my delay macro, if anyone's interested" at http://paste.lisp.org/display/63238#1

16:13 rhickey_: cemerick: you would still want to check :fn before calling it

16:19 cemerick: ah, I see that now. 'twas my first usage of transactions. Thanks for the pointer.

16:33 Chouser_: with seque's fill now leaving the thread instead of blocking, it has diverged even further from what I need to wrap a SAX parser.

16:34 rhickey_: right, because seque is pull and SAX is push

16:34 Chouser_: What torments me is I'll still need the LBQ, the agent management, exception propagation, etc. So it'll still look really similar, but different enough to be unusable.

16:35 but I think I just need to get over myself.

16:35 rhickey_: I had the seque in 2 parts, as I had described, seq->queue, queue->seq, with the only connecting point being the weak-ref

16:36 then I got discouraged about the weak ref.

16:36 Chouser_: heh. yeah. :-/

16:36 rhickey_: you still have to solve the close problem

16:37 After ECOOP, I'm going to look hard at Closeable for LazySeq, and also for direct cde-gen for LazySeq, as it has become so important to Clojure

16:37 Chouser_: cool.

16:38 that starts week from now?

16:38 are you ready?

16:38 rhickey_: I give talks on Monday and Tuesday - working on my slides now

16:38 Chouser_: huh. I thought you were working on seque and delay. ;-)

17:02 jgracin: If I have a Clojure script in the classpath, is there a way to load it from REPL?

17:03 Chouser_: (.loadResourceScript RT "foo.clj")

17:03 (.loadResourceScript clojure.lang.RT "foo.clj")

17:04 jgracin: Chouser_: Beautiful! Thanks!

17:04 Chouser_: np

18:00 StartsWithK: hi

18:01 i now have running gears demo as clojure applet at http://kreso.mooo.com/gears.html

18:01 but, i had to copy all needed file in GearsApplet.clj..

18:03 bpattison: geospatial=> (defn f2 [ x y ] (pr "f2=" x y))

18:03 #'geospatial/f2

18:03 geospatial=> (defn f3 [x & more] (let [s (seq more)] (pr x) (f2 s) ) )

18:03 #'geospatial/f3

18:03 geospatial=> (f3 1 2 3)

18:03 1java.lang.IllegalArgumentException: Wrong number of args passed to: f2

18:03 I'm stuck trying to get the right number of arguments to f2 -- any ideas?

18:47 rhickey_: bpattison: if a function takes args and you want to use the contents of a seq as the args, you need to apply the function. If you just call it, the seq will be passed as a single arg:

18:47 (defn f3 [x & more] (let [s (seq more)] (pr x) (apply f2 s)))

20:14 bpattison: rhickey: thank you -- I was struggling with that for a while

23:40 arohner: hello. Is this a good place to ask newbie questions?

23:40 I have

23:40 rhickey_: sure

23:41 arohner: (def foo [a b c] (println a b c))

23:41 is there a way to pass a seq of length 3 as an argument to foo?

23:42 I believe that's called splatting in ruby

23:42 rhickey_: (apply foo [1 2 3])

23:42 arohner: ah, thanks

23:47 can you call apply on a java method?

23:50 rhickey_: no

23:52 arohner: ok, thanks

23:53 BTW, thanks for creating clojure. I've been really happy with it

23:56 rhickey_: you're welcome!

Logging service provided by n01se.net