#clojure log - Mar 27 2009

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

2:08 yangsx: I have an extended assert that print some additional info for debug purpose, but sometimes there is an assertion failure without preventing any such info at all at repl if the assertion is buried in some depth.

2:08 Is that expected behavior?

2:08 s/printing/preventing

2:36 hiredman: what kind of try/catch stuff do you have around the assertion?

5:10 Raynes: Weee my Clojure text editor is almost complete. Ya know. Creating substitutes for the basic applications that come with Windows is a great way to learn a language let me tell ya.

5:10 * Raynes goes to sleep.

5:16 antifuchs: Raynes: congratulations

5:47 AWizzArd: Raynes: sounds nice

6:13 antifuchs: now to hack some more on the 3d modeller plugin - I think I should be able to print a clojure-generated 3d model in very few days (:

7:27 durka42: antifuchs: awesome, what library are you using?

7:27 antifuchs: I'm writing a plugin for Art of Illusion. this lets me interactively (in slime) write code that creates 3d models

7:28 that's inspired by a friend's MetaCADEvaluator plugin for same

7:28 durka42: nice

7:29 antifuchs: it is! it's rewarding on its own already, but since it's for a 3d printer, I even get to play with the stuff this creates afterwards (:

7:30 durka42: 3d printers are nearly as cool as clojure

7:31 silly me i figured you meant "print" to screen

7:31 antifuchs: heh. I'm not yet decided on the ordering on coolness; but both are pretty awesome (:

7:31 durka42: but you meant print to _reality_

7:31 antifuchs: oh no. print to toy (-:

7:57 noidi: is there a function like nth that counds from the end of the collection instead of the beginning?

7:58 counts

7:58 in python i could use my_list[-2] to get the second-to-last item from a list

7:59 Cark: i dion't think there is

8:01 actually this might be a good sign you need a vector rather than a list

8:02 noidi: i'm using a vector, actually

8:03 Cark: ah well tyhen it's (get my-vector (- (count my-vector) 2)

8:03 noidi: thanks!

8:04 Cark: ,(let [v [1 2 3 4 5]] (v (- (count v) 2)))

8:04 clojurebot: 4

8:06 noidi: i'd like (nth [1 2 3 4 5] -2) better :)

8:07 Cark: you may write a function to do this =)

8:07 noidi: yeah, i know

9:01 antifuchs: hm, is there a way to get a more meaningful backtrace from clojure than what I'm seeing in slime right now? the top frame is always clojure.lang.Compiler.eval, followed by similarly useless ones /-:

9:03 (I got the issue resolved eventually, but it would have helped enormously to know which function the breakage was in)

9:09 drewr: antifuchs: Hit 1 to see expand each cause.

9:10 antifuchs: OH. wow. (:

9:10 I was so used to seeing one useful and one useless restart from sbcl that I completely ignored the second one

9:10 thanks!

9:10 sellout: antifuchs: Zing!

9:11 antifuchs: hey sellout (-:

10:29 AWizzArd: Do we have an expert for regular expressions here?

10:30 I want to know what follows an underscore, but only if the string contains exactly one underscore

10:30 (re-find #"" "hello_world") ==> world

10:30 (re-find #"" "hello_sweet_world") ==> nil

10:31 hiredman: ,(re-find #"{^_]_[^_]" "hello_world")

10:31 clojurebot: Illegal repetition {^_]_[^_]

10:31 hiredman: ,(re-find #"{^\_]\_[^\_]" "hello_world")

10:31 clojurebot: Illegal repetition {^\_]\_[^\_]

10:31 hiredman: ,(re-find #"[^_]_[^_]" "hello_world")

10:31 clojurebot: "o_w"

10:32 hiredman: ,(re-find #"[^_]+_[^_]+" "hello_world")

10:32 clojurebot: "hello_world"

10:32 hiredman: ,(re-find #"[^_]+_[^_]+" "hello_world_sweet")

10:32 clojurebot: "hello_world"

10:33 AWizzArd: I was thinking about negative lookaheads: an _ not followed by an underscore (re-find #"_(?!_)" some-string), but that does not work out

10:38 hiredman: ,(re-find #"_[^_]+" "hello_world_sweet")

10:38 clojurebot: "_world"

10:38 hiredman: ,(re-find #"_[^_]+" "hello_world")

10:38 clojurebot: "_world"

10:39 AWizzArd: They are all pretty close.

10:39 These damn regexps ;)

10:43 hiredman: ,(re-find #"_[^_]+$" "hello_world_sweet")

10:43 clojurebot: "_sweet"

10:43 hiredman: bah

10:43 ,(re-find #"[^_]_[^_]+$" "hello_world_sweet")

10:43 clojurebot: "d_sweet"

10:43 hiredman: snort

10:44 * AWizzArd gives up

10:44 AWizzArd: I will do it manually

10:45 hiredman: thanks for your suggestions

10:46 Chousuke: (re-find #"_[^_]([^_])*" "hello_word_test")

10:46 ,(re-find #"_[^_]([^_])*" "hello_word_test")

10:46 clojurebot: ["_word" "d"]

10:46 Chousuke: hm, interesting :P

10:48 ,(re-find #"_[^_]([^_])+" "hello_word_test")

10:48 clojurebot: ["_word" "d"]

10:52 Holcxjo: ,(re-find #"^[^_]*_([^_]+)$" "hello_word")

10:52 clojurebot: ["hello_word" "word"]

10:52 Holcxjo: ,(re-find #"^[^_]*_([^_]+)$" "hello_word_test")

10:52 clojurebot: nil

10:52 Holcxjo: ,(re-find #"^[^_]*_([^_]+)$" "helloword")

10:52 clojurebot: nil

10:53 Holcxjo: ,(re-find #"^[^_]*_([^_]+)$" "_world")

10:53 clojurebot: ["_world" "world"]

11:00 Holcxjo: ,(map (fn [text] (let [match (re-find #"^[^_]*_([^_]+)$" text)] (list text (if match (nth match 1))))) (list "" "hello" "hello_" "hello_world" "hello__world" "hello_world_test"))

11:00 clojurebot: (("" nil) ("hello" nil) ("hello_" nil) ("hello_world" "world") ("hello__world" nil) ("hello_world_test" nil))

11:03 AWizzArd: This regexp which solves this "simple task" is protected against being found.

11:03 Holcxjo: AWizzArd?!?

11:04 AWizzArd: I mean, we can't find it.

11:04 Holcxjo: This one: #"^[^_]*_([^_]+)$" ?

11:04 AWizzArd: "Return what follows an underscore. Match only if the string contains exactly one underscore".

11:05 Holcxjo: That's what mine does. Or not?

11:05 AWizzArd: ,(re-find #"^[^_]*_([^_]+)$" "hello_a_xyz")

11:05 clojurebot: nil

11:05 AWizzArd: ,(re-find #"^[^_]*_([^_]+)$" "hello_a")

11:05 clojurebot: ["hello_a" "a"]

11:06 AWizzArd: yes okay, this one is doing it, it seems

11:06 Holcxjo: Might want to make the last "+" a "*" in case the empty string is acceptable as being after the underscore

11:06 AWizzArd: ,(re-find #"^[^_]*_([^_]*)$" "hello_")

11:06 clojurebot: ["hello_" ""]

11:07 AWizzArd: Holcxjo: grats :)

11:07 Holcxjo: np

11:14 AWizzArd: clojurebot: max people

11:14 clojurebot: max people is 164

12:05 tsdh: Does anyone have an example of :let in a for comprehension?

12:05 hiredman: ,(for [x (range 10) :let [y (* x x)]] y)

12:05 clojurebot: (0 1 4 9 16 25 36 49 64 81)

12:06 tsdh: Thans, hiredman.

12:22 scottj_: Is anyone able to run the code from this genetic mona lisp solution? (http://npcontemplation.blogspot.com/2009/01/clojure-genetic-mona-lisa-problem-in.html) I get "java.lang.Exception: Unable to resolve symbol: draw-polygon in this context"

12:24 kefka: I asked this question last night and couldn't get a conclusive answer. Does Clojure have the problem of keywords and strings getting interned on reads, the way CL does?

12:24 The reason I'm asking is that I'm worried about memory leakage.

12:24 (Almost no one was on last night when I asked.)

12:25 scottj_: kefka: I think I remember Rich talking about that in one of his screencasts, probably the lisp one.

12:25 strings are java strings, if that helps answer the question

12:28 see fourth paragraph, http://netzhansa.blogspot.com/2008/10/trying-clojure.html

12:29 danlarkin: kefka: the reader does not intern

12:30 symbols, I know, at least

12:31 hiredman: depends what you mean by "intern"

12:32 well

12:32 hmm

12:35 brianh2: kefka: i've been poking around a little

12:35 found this http://www.thesorensens.org/2006/09/09/java-permgen-space-stringintern-xml-parsing/

12:36 which pointed to this http://www.javaworld.com/javaworld/javaqa/2003-12/01-qa-1212-intern.html

12:39 kefka: Ok, so it looks like there's nothing to worry about with symbols piling up and eating memory. Is the same true of keywords?

12:39 clojurebot: http://clojure.org/data_structures#toc10

12:40 brianh2: best i can tell, keywords are symbols & therefor interned in the permgen space

12:41 hiredman: erm

12:41 I am pretty sure what gets interned is the string behind the keyword or symbol

12:41 ~def c.l.Keyword

12:44 cemerick: symbol and keyword strings are interned, and keywords themselves are interned as well (of course, using a separate facility from the standard lib's String.intern())

12:45 Of course, there's nothing keeping you from creating a symbol whose string isn't interned.

12:45 ,(identical? 'foo 'foo)

12:45 clojurebot: false

12:45 brianh2: that's semantics. but ok. to be precise. it would appear that every keyword that is created generates a symbol that is then placed into a map as the key to the keyword itself

12:46 cemerick: yeah.

12:47 brianh2: that symbol causes the ns name & the keyword name to be interned into the permgen space

12:47 cemerick: The direct Keyword constructor is private right now, but if there was a compelling case for the non-interned keyword strings, I'll bet that could be changed.

12:47 clojurebot: for is not used often enough.

12:47 cemerick: Yes.

12:48 I'd be surprised if that was somehow absolutely a requirement, though. Likely just a way to ensure good space/performance tradeoffs by default in maps, etc.

12:49 brianh2: & since the keyword table is private & nothing ever, as far as i can tell, removes anything from it, keyword strings will never be GCd

13:04 rsynnott: what do you want non-interned keyword strings for?

13:08 brianh2: rsynnott: i don't ;) i was just interested in the implications of using the String.intern() feature for keywords/symbols

14:26 Lau_of_DK: Good evening gents

14:28 pjstadig: good afternoon

14:29 mozinator: I would like to ask a question, I tried to search for it, but I couldn't find it.

14:29 Is it possible to inherit a java class and override methods ?

14:29 hiredman: ,(doc proxy)

14:29 clojurebot: "([class-and-interfaces args & fs]); class-and-interfaces - a vector of class names args - a (possibly empty) vector of arguments to the superclass constructor. f => (name [params*] body) or (name ([params*] body) ([params+] body) ...) Expands to code which creates a instance of a proxy class that implements the named class/interface(s) by calling the supplied fns. A single class, if provided, must be first. If not provid

14:30 hiredman: if you want to add new methods you need to use gen-class or gen-interface

14:30 mozinator: hiredman, thanks for the pointer!

14:30 clojurebot: for is not a loop

14:33 durka42: why did clojurebot start speaking when he is not being spoken to

14:33 test:

14:34 he suddenly became sentient!

14:34 ~he suddenly became sentient!

14:34 clojurebot: CLABANGO!

14:34 durka42: so just "for"

14:34 sellout: durka42, I think it's the comma

14:34 eh, guess not

14:34 pjstadig: hiredman, suddenly he became sentient!

14:34 huh

14:35 cmvkk_: ~

14:35 clojurebot: BDFL is Benevolent Dictator For Life (a.k.a. Rich Hickey)

14:35 cmvkk_: hmm

14:36 cemerick: he says something without prompting once every 20 messages or something now

14:36 sellout: That's a long time!

14:36 hiredman: everytime (= 1 (rand-int 20))

14:36 cmvkk_: just anything? or something relating to the last message

14:37 hiredman: it treats the last message as if it was addressed to it

14:37 clojurebot: it is too

14:37 hiredman: ^-

14:37 cemerick: hiredman == crazy mad social scientist ;-)

14:41 p_l: markov model, eh?

14:41 pjstadig: sorry

14:41 i was trying to teach clojurebot to argue with me

14:41 it is too/it is not/it is too

14:42 but everytime i tried to get it to learn to respond to "it is too" he thought (= 'it 'too)

14:42 hiredman: heh

14:42 clojurebot: it is too?

14:42 clojurebot: it is too

14:48 Lau_of_DK: mozinator...

14:48 ~proxy?

14:48 clojurebot: proxy is <Chouser> proxy teases with its ease of use, then suddenly betrays.

14:48 Lau_of_DK: Consider reading up on gen-class instead :)

14:48 hiredman: *shrug*

14:48 mozinator: Lau_of_DK, will do, thanks

14:48 hiredman: ~works on my machine

14:48 clojurebot: http://haacked.com/images/haacked_com/WindowsLiveWriter/IConfigMapPathIsInaccessibleDueToItsProt_1446B/works-on-my-machine-starburst.png

14:50 pjstadig: ~is too!

14:50 clojurebot: is not!

14:50 pjstadig: ~is not!

14:50 clojurebot: is too!

14:50 pjstadig: sweet

14:51 clojurebot has sass

14:53 ~is not!

14:53 clojurebot: is too!

14:53 pjstadig: ~is not!

14:53 clojurebot: is too!

14:53 pjstadig: ~is not infinity!

14:53 clojurebot: is too infinity +1!

14:53 pjstadig: d'oh

14:54 beaten by a bot

15:11 AWizzArd: Some days ago Rich gave a talk. A lot of twitter users were writing about it. Is there an audio/video file available?

15:11 sellout: AWizzArd: It was definitely recorded.

15:12 Don't know when/where the video will be available.

15:12 hiredman: the infoq is not yet, it maybe a while before they put it up, the skillsmatters is up

15:12 sellout: It was (I think) 5 hours.

15:12 hiredman: clojurebot: skillsmatter?

15:12 clojurebot: Titim gan �ir� ort.

15:12 pjstadig: infoq will probably release video from qcon, but they dribble it out

15:13 may not be months

15:13 sellout: hiredman: I think he's referring to the ILC one, but not sure.

15:13 hiredman: oh

15:13 pjstadig: oh ILC would be nice

15:13 * Raynes huggles hiredman

15:13 hiredman: what?

15:13 clojurebot: ?Que?

15:14 Raynes: <3

15:14 rhickey_: in past 2 weeks - 2 talks + 1 interview at QCon, a talk at Java group in London, a short talk at semantic web meetup in NYC, 5 hour tutorial and a panel at ILC

15:14 pjstadig: http://skillsmatter.com/podcast/java-jee/clojure-for-java-programmers

15:15 hiredman: zouch

15:15 Raynes: Been busy.

15:17 * Raynes has been added to a Java IDE project and is allowed to use Clojure in place of Java for any development I do.

15:17 Raynes: \o/

15:17 rhickey_: Raynes: awesome!

15:17 Raynes: We all know, Java totally needs moar IDE's.

15:18 :D

15:19 mrsolo_: well eclipse clojure plug in is badly needed :-)

15:20 Raynes: mrsolo_: Clojure-dev already exists.

15:20 pjstadig: http://www.swnyc.org/index.php?title=AllegroGraph%2C_the_Semantic_Web_%26_Clojure_Updates

15:20 AWizzArd: Raynes: very good, you make my point. I am argumenting since months that Clojure *will* open job opportunities. Clojurists will sneak into Java companies, probably Startups, who will be willing to trade "cryptic code" (Clojure *g*) for the increased productivity.

15:20 mrsolo_: raynes: exists last time i checked few months back it is still not working too good

15:20 slime is sufficient imho if you stay inside clojure

15:20 but when you start doing java interop stuffs....

15:20 clojurebot: ?

15:21 Raynes: mrsolo_: It's working better now, but with no offense to Laurent as I know he tries hard, Enclojure is better.

15:21 AWizzArd: pjstadig: thanks for this video link

15:21 pjstadig: AWizzArd: np

15:22 AWizzArd: Raynes: Enclojure still has to fight with the enormous complexity of NetBeans.

15:22 dysinger: There already is a clojure IDE - it's called emacs + slime :P

15:23 Raynes: Enclojure works for me. That's my disclaimer.

15:23 AWizzArd: it's what I am using too

15:23 mrsolo_: raynes: it takes resources to get plug in working; i don't envy him :-)

15:23 AWizzArd: but Enclojure will hopefully catch up over time

15:23 mrsolo_: as for enclojure that is the thing

15:23 i don't use netbeans and really don't want to learn another ide

15:23 again

15:23 dysinger: I tried both the eclipse & netbeans flavors yesterday - no thanks

15:24 I can appreciate they are good for the java crowd though

15:24 emacs + slime + jswat is all I need for now.

15:24 brianh2: rhickey_: how were you and Clojure received at ILC?

15:24 AWizzArd: dysinger: after using slime+CL for some years it is difficult to use something else, but I think sooner or later Enclojure will be able to do all that nice stuff too, and then even more.

15:25 hiredman: durka42 has edged out cconstantine url wise

15:25 dysinger: yeah - I won't give up emacs' awesome for now.

15:25 but I can see how a Java IDE _could_ do better on the java parts.

15:25 (debugging etc)

15:26 AWizzArd: the nice thing is that the debugger is already included in NetBeans, as well as the Gui builder.

15:26 dysinger: jswat is the netbeans debugging AFAIK

15:26 true - I guess I'll be happy to play with it all.

15:28 AWizzArd: It is just very very complicated to program NetBeans. The guys who implement plugins for emails or vi for Clojure editing have a way easier job.

15:28 clojurebot: for is not a loop

15:34 jwinter_1: What am I doing wrong with loop/recur here http://gist.github.com/86841 ?

15:35 cmvkk_: your recur is inside a vector, so it's not in tail-call position.

15:36 pjstadig: http://gist.github.com/86844

15:36 jwinter_1: ah, thx very much

15:37 sellout: jwinter_1: You can't just wrap [] to put a block in your if branch

15:37 cmvkk_: well you can, provided you don't care about the return value...and provided you aren't trying to recur

15:37 sellout: If that did do something, I don't think it's what you'd want.

15:38 cmvkk_: ah, true enough

15:38 is that a common idiom in clojure?

15:38 cmvkk_: no

15:38 sellout: *phew*

15:38 cmvkk_: it's bad practice of course, and i've never seen anyone do it before...i was just pointing out that it does technically work

15:39 jwinter_1: the do block was what I was looking for, I just stumbled onto the fact that that vector would execute what's inside

15:40 sellout: cmvkk_: I thought it was a mistake akin to the CL newbie one of (if foo bar ((print baz) quux))

15:40 but it seems to be of a different kind

15:41 cmvkk_: yeah, although that example at least doesn't work at all

15:42 sellout: cmvkk_: Yeah, thankfully.

15:48 arohner: more and more, I find myself using refs of maps instead of plain maps, just so I can validate them

15:48 validators are awesome

15:49 AWizzArd: arohner: do you have a minimal example?

15:50 arohner: hrm, not a short one

15:50 AWizzArd: What is a validator?

15:51 arohner: it is a function that can be attached to a ref

15:51 if you try to change the ref, the validator is called

15:51 hiredman: arohner: you could write a validating version of assoc

15:51 that uses a validator from the maps metadata

15:51 arohner: if the validator throws an exception or returns false, the transaction fails

15:52 hiredman: that's interesting. I was thinking of a validating struct-map

15:52 ,(doc ref)

15:52 clojurebot: "([x] [x & options]); Creates and returns a Ref with an initial value of x and zero or more options (in any order): :meta metadata-map :validator validate-fn If metadata-map is supplied, it will be come the metadata on the ref. validate-fn must be nil or a side-effect-free fn of one argument, which will be passed the intended new state on any state change. If the new state is unacceptable, the validate-fn should return fa

15:53 sellout: arohner: But you don't need a validator if you're not going to modify the map, so why would you use a ref rather than the map directly?

15:54 hiredman: metadata and map destructuring are my features of the week

15:54 sellout: Rather, in which cases where you would have used the map directly in the past do you now use a ref?

15:55 arohner: I have a few different places where I create instances of the same kind of struct map

15:55 and I sometimes I find bugs where one fn that creates the struct map was doing it incorrectly

15:56 so maybe I want a validating struct-map

15:56 hiredman: very interesting

15:59 antifuchs: so - here's my finished 3d-printable part: http://github.com/antifuchs/aoi-swank-plugin/blob/1987fb6d3477fc5835d1c37b2762ac2cf82c5696/examples/dishwasher-part.clj (the exact same thing was printed before, as http://reprap.soup.io/post/15859377 (:

15:59 hiredman: ~def defstruct

16:00 AWizzArd: antifuchs: sounds nice

16:00 apropos bugs, please check out my posting in the Google Group: http://groups.google.com/group/clojure/browse_frm/thread/7a48f48e4b197a15/bcaf06d233cde839

16:00 antifuchs: I'm still not entirely happy with the surface syntax and the repeated need to transform by (90 0 0), but I'm optimistic that this will be very nice soon (:

16:00 AWizzArd: wow

16:02 sellout: antifuchs: You integrated with aol to make a dishwasher knob?

16:02 antifuchs: And you have a RepRap?

16:02 antifuchs: sellout: we have one at the metalab (:

16:02 AWizzArd: arohner: if rhickey decide to implement gradual typing, then you could catch some hard to find bugs

16:03 sellout: antifuchs: I'd ask you to print me one if I was near Austria.

16:03 arohner: AWizzArd: what is gradual typing?

16:03 sellout: arohner: see Typed Scheme

16:03 antifuchs: sellout: sure thing! new york may be easier for you (:

16:03 sellout: nyc resistor sell kits with space for 10x10x10cm models for $750

16:04 sellout: Nice, danke.

16:04 AWizzArd: arohner: it is mentioned in that Google Posting. But the basic idea is: it is extremly granular static typing. You can have as few or as much you want.

16:04 antifuchs: they're very good, apparently (and I am pondering buying one of their extruders) (:

16:04 AWizzArd: Between 100% dynamic typing and a 100% statically typed program everything is possible.

16:04 arohner: AWizzArd: interesting. thanks

16:04 AWizzArd: And with a global switch one could even turn it off, if one really does not like static typing and a lib one is using supports it.

16:05 Clojure could simply use metadata for communicating what it wants the compiler to treat as static code

16:05 You could for example have one function in your whole code base which can perform type checks for one of its 4 parameters

16:06 This would allow the compiler to let you know that you made a type error at some point or not. You would do this only for code that you want to be static (= not changeable during runtime).

16:08 and this is also nice for editing source code

16:08 The IDE could access the type information as well, and allow you several nice completions/checks during edit time.

16:09 arohner: very cool

19:52 zakwilson: I'm trying to use contrib.json.read. There seems to be no documentation. If I have a URL and want a PushbackReader, what's the standard way to get one?

19:53 danlarkin: you know what /is/ documented... :-o

19:55 zakwilson: I know the Java API has lots of docs, but I'm not finding what I need because I don't know where to look. I'm trying to use the URL class, but that doesn't seem do what I need.

19:57 Ahh... I think I figured it out. That has to go through way too many classes.

20:04 danlarkin: oh, nah I was just plugging clojure-json

20:04 but I'm glad you got it working

20:04 slashus2: danlarkin: I do like your json library.

20:06 danlarkin: cool

20:06 thanks

20:07 lpetit: Hello, is the fact that thread-local bindings are not propagated to child threads a design choice, a tradeoff made for performance considerations, both ?

20:08 I meant thread local bindings of vars, of course

20:08 zakwilson: I think it's because they wouldn't be thread-local if they were.

20:08 slashus2: danlarkin: The decode-from-string is a nice feature to have.

20:10 lpetit: I meant thread-local values, with the same property a thread-local binding has towards the stack of bindings : changes done via new 'binding or set! calls would not affect threads higher on the stack call

20:10 rhickey_: lpetit: it's a design choice - closures in general are created without knowing the context in which the thread that will run them has been created - there are perf issues too

20:18 lpetit: rhickey_: what is the expected set of use cases for global vars ? A recent post on the ml made what I have considered a valid point. Say I'm the user of an interesting library's function called foo. foo accepts a closure. For debugging purposes, I place some (println) calls in my closure, and create in my thread a thread local binding for *out* to a proper value. Now if the next version of...

20:18 ...the library has optimized its foo function for using several threads (maybe replacing a call to map by a call to pmap ...), suddenly I loose some traces in my log.

20:19 rhickey_: lpetit: you can always create a closure that includes whatever bindings you need

20:21 but every closure creation can't capture every dynamic binding

20:23 lpetit: rhickey_: yes, and I remember Christophe Grand already posted such a solution (macroified for ease of use) in his blog. But then one has to know in advance which bindings to further propagate. That may be impractical with a big code base, or code written by big teams ?

20:25 rhickey_: again, please: when you write "but every closure creation can't capture every dynamic binding", are you saying "that would be ideal solution, but it is just impossible to do it efficiently", or are you saying "it is not affordable to impose to users that each closure creation capture the current dynamic binding" ?

20:26 rhickey_: there are as many reasons why you might want to return a closure that leverages the dynamic context in which it is run - threads are not really relevant - dynamic context is just that - the context in which you are run, not the one in which you are created

20:27 i.e. any function that prints would capture the state of *out* at its definition point

20:27 not what you want

20:28 grosours: hi

20:29 lpetit: rhickey_: yes, my concern is about making the vars behavior recursive among the thread hierarchy, not only between the thread that holds the root bindings (but is there one anyway that can be distinguished as such), and a thread where I rebind the var.

20:30 rhickey_;ok concerning closures and the capture of values of global variables, because then it would just be lexical binding considering that global vars are in the "outermost" lexical scope. And I agree they would certainly not deserve the "dynamic" qualificative then :-)

20:32 rhickey_: lpetit: what thread hierarchy?

20:32 thread pool threads aren't 'under' specific application threads

20:33 lpetit: rhickey_: argh, you're right

20:33 rhickey_: it's best to leave threads out when thinking about this

20:33 it has to do with the meaning of dynamic scope

20:34 which is a runtime, not definition-time, thing

20:37 lpetit: Sorry I don't understand, the main concern of my question is precisely to think about this thread stuff. Considering that threads created e.g. by pmap aren't technically child threads of the application thread, one might still consider they can be "logically" considered child threads, and inherit for their vars the bindings of the "logically" parent thread ? Technical and performance...

20:38 ...problems set apart, would it make sense if such a change could be made possible ?

20:39 rhickey_: no - imagine you create a closure that prints, and return it to someone that later binds *out* and calls it - what do you expect to happen? it has nothing to do with threads or pmap

20:40 cmvkk_: i thought you meant like (binding [*foo* true] (send-off ag some-fn)) then expecting some-fn to see *foo* as true.

20:43 rhickey_: (send-off ag #(binding [*foo* true] (some-fn %)))

21:01 lpetit: rhickey_: if as the closure creator I write it so that it prints, then at the time I write the closure, I'm OK to go with the normal behavior of dynamic variables: I don't know what the binding will be at call time, it will be set by the context. Now, as the user of the closure, I may want to specify a binding. As you just posted, I then have the possibility to add a clojure above the...

21:01 ...function to rebind the value. But please admit it's far from ideal for at least 3 reasons:

21:01 1) I must repeat (and think about it) every time I have to make such a call. Even with some macro it's subject to errors. And if I have the value in a global already, I think I must write this if I want it to work : (send-off ag (let [let-foo

21:01 *foo*] #(binding [*foo* let-foo] (some-fn %))))

21:01 2) Sometimes I guess it will be difficult to remember all the bindings that *must* be passed as in the example aboe with send-off. And I fear things may get worse with big code base where one uses a closure created by lib B, passing it to lib C ...

21:01 3) sort of leaky abstraction: if a user of a function provided by a lib must know if it is possible the function will split the work in separate threads for performance reasons or not, then I guess the technique of enclosing in a closure that will rebind before ... may well become "the way" to be sure it will work as expected.

21:01 So then again: if closures or even classic functions should not rely on global vars because the *user* of the closure or the function call can't be sure the binding it placed on the needed vars went away for a good reason and in a predictable way, how to blindlessly rely on them on my code ? And if the answer to be systematically certain that I will not have surprises is to rebind in a...

21:01 ...wrapper closure, would propagating the global vars values to "logical" child threads (if ideally possible) be a good thing compared to the current state of the art (technical, performance considerations set apart)

21:05 rhickey_: a final word and I go to sleep and don't bother you more tonight : I'm asking that because I wanted to play with clojure java code, trying some implementations ideas that could solve the technical and performance problems. But then, if at the end of the road it is not interesting for design considerations I haven't understood yet, I'll be a little bit disappointed by myself...

21:09 rhickey_: anyway, thanks for having exchanged ideas and knowledge with me, regards, Laurent.

21:55 duderdo: Hi

21:57 What would be the best way to let slime know my CLASSPATH? The function in the clojure wiki seems a bit verbose

22:07 sudoer: hi all,if i want to start on some web programming for clojure ,should I use compojure/other library or just do my own thing? I am learning clojure currently

Logging service provided by n01se.net