10:06 Chouser: Shouldn't (binding [x 5] x) just return 5?
10:09 drewr: It does for me.
10:09 user> (def x 1)
10:09 #<Var: user/x>
10:09 user> (binding [x 5] x)
10:09 5
10:10 Chouser: oh! you have to def it first.
10:11 I think I used to know that. Thanks!
10:12 drewr: What I don't understand is why you can't just use let.
10:12 Chouser: you can, but they do different things.
10:12 let is lexical. you can use x inside the syntactic boundaries of the (let ...)
10:12 bindings survive through function calls.
10:12 "dynamic binding" I think it's called.
10:13 (defn prnx [] (prn x))
10:14 (binding [x 5] (prnx)) --> prints 5
10:14 (let [x 5] (prnx)) --> crashes, because x is not defined in prnx
10:14 cgrand: chouser: dynamic scoping
10:14 Chouser: cgrand: thanks.
10:14 rhickey: both correct
10:16 cgrand: rhickey: thanks
10:16 Chouser: so shouldn't this work? (binding [x 5] (for [i [1 2]] [i x]))
10:16 drewr: Chouser: The first defn won't succeed though.
10:16 Chouser: drewr: you still have to do a (def x) earlier, like you showed me.
10:19 does that binding...for crash for anyone else?
10:20 drewr: OK, looking at the definitions of print and println helps me understand how that's useful.
10:24 rhickey: Chouser: crash?
10:24 abrooks: I think he meant took an exception.
10:24 Chouser: well, an exception. java.lang.IllegalStateException: Var x is unbound.
10:24 sorry. sloppy use of English.
10:24 rhickey: remember for is lazy, better consume it all before the binding goes out of scope
10:25 Chouser: oh! weird...
10:25 a closure doesn't hang onto its dynamic scope?
10:25 abrooks: Chouser: That one agin... :)
10:25 rhickey: the seq is outliving the binding
10:25 abrooks: rhickey: Is the best way to (doall (for ....)) ?
10:25 rhickey: closure == lexical scope, bdingind == dynamic scope, so no
10:25 binding
10:26 Chouser: abrooks: I didn't realize this was the problem you were having.
10:26 abrooks: abrooks: That was the issue the other night. Look at the noise.log.
10:26 Chouser: abrooks: yeah, I thought I understood at the time, but apparently I didn't.
10:26 rhickey: abrooks: dorun or doall, depending on if it's all side effects or you want to retain the seq
10:28 abrooks: rhickey: The other night I got bitten by lazy for when I stuck it inside a (do ..) because I wanted for for sideffects (sending agents functions) but wanted the form to have a different value. The do allowed the for to be lazy. I then put a (doall ) in and it worked but only after I figured it out.
10:29 Should non-terminal slots in do be eager?
10:30 rhickey: abrooks: no
10:30 abrooks: Hm. For my own understanding, why? :)
10:30 Or why not, actually.
10:30 rhickey: I do think 'for' implies iteration for people though, so this is a common mistake
10:31 abrooks: Yes. The imperative meme has clamped onto all of our brainstems and is quite embedded.
10:31 Chouser: FWIW, I'm fine with a 'for' being lazy, it was the behavior of binding and closure that threw me.
10:31 rhickey: abrooks: there's not really a notion of a terminal slot, they all move together like an odometer
10:32 Chouser: items in 'do' are sequential, aren't they?
10:32 abrooks: rhickey: In a (do ..)?
10:32 I thought they were as Chouser said.
10:33 rhickey: abrooks: I thought you meant for, there's no laziness in do
10:34 abrooks: rhickey: (do ) allows for to be lazy.
10:34 rhickey: abrooks: for is always lazy
10:34 abrooks: (do (for [x (range 10)] (println x)) 9)
10:35 rhickey: I'm probably not saying this right.
10:35 If I remove the 9 in the above, (do ) consumes all of the for. In the non-terminal slot, it doesn't.
10:36 rhickey: abrooks: no, the repl is what consumes the for, in printing the result
10:36 abrooks: (do (for [x (range 10)] (println x)))
10:36 rhickey: (def x (do (for [x (range 10)] (println x))))
10:36 x
10:37 abrooks: Ah. And in the general case, /something/ is consuming the last value of (do ).
10:37 rhickey: maybe
10:38 abrooks: The sticking point for me is that the values of other slots of do are thrown away and are never consumed, right?
10:38 rhickey: right, do is for side effects
10:38 abrooks: So if do is for side effects then should it be eager?
10:38 At least for non-terminal slots?
10:39 ^should it^shouldn't it
10:39 rhickey: (do (foo) (bar) (baz))
10:39 * abrooks needs more tea.
10:39 rhickey: how does do know if foo returns a lazy seq that needs forcing?
10:40 abrooks: Should I not be using (for ) for iteration or should I always wrap (doall ) around it when using it in a non-terminal (do ) slot?
10:40 drewr: rhickey: What's the reason for Clojure being case-sensitive? I always thought it was considered a feature of Lisps to write lowercase, but refer to code with uppercase.
10:40 rhickey: Chouser: you can use a dynamic value in an expression that returns a lazy seq by capturing it:
10:41 drewr: For example, this conversation would be much clearer if we could write DOALL, FOR, etc.
10:41 rhickey: (def x 1)
10:41 user=> (binding [x 5] (for [i [1 2]] [i x]))
10:41 ([1 5] [2 1])
10:41 user=> (binding [x 5] (let [x x] (for [i [1 2]] [i x])))
10:41 ([1 5] [2 5])
10:42 abrooks: drewr: I'm case insensitive. I was born that way. The doctors think it's my brain not my eyes.
10:42 rhickey: drewr: I consider CL's treatment of case a major misfeature
10:43 drewr: rhickey: Scheme is case-insensitive too.
10:43 * abrooks actually prefers case sensitivity and would be frustrated if he had to type in upper-case.
10:43 drewr: abrooks: That's an argument for case-insensitivity. :-)
10:43 abrooks: drewr: In conversation it can be fine (and clear) to type bare language constructs upper-case.
10:45 drewr: I think the best argument for case sensitivity is that it forces other people's code to look the same.
10:45 rhickey: case insensitivity is information-lossy
10:45 can be a huge problem when identifiers have to go through Lisp in/out of the outside world
10:45 think about Clojure's java interop
10:47 drewr: That's what I was trying to get to. I wanted to know if it was purely subjective, or if you had a technical reason. When you're interoperating with case-sensitive symbols from a host lang, it would probably be a nightmare to allow arbitrary case.
10:47 I buy that.
10:48 Although, as a personal preference, I tend to like CL and Scheme's case agnosticism.
10:48 rhickey: heh - one of my number one problems with CL
10:51 jteo: imho, worth the price for java interop.
10:51 drewr: jteo: Yeah, I agree.
10:53 I can see how ambiguity in case can lead to maintenance catastrophes in large codebases (I've never written anything big enough in Lisp to have an issue).
10:53 rhickey: I simply think it's wrong for the user to enter x and the system to change it to X, so ascii, so 1970s...
10:54 greatly reduces the utility of symbols
10:55 java interop/natural language/xml
10:56 jteo: minor nitpick: i'm confused by the use of "[ ]". :)
10:56 rhickey: confused in what way?
10:57 jteo: as opposed to common lisp, where you would only ever see "( )" encompass variables.
10:58 rhickey: I find Clojure much easier to read than CL
10:59 jteo: i admit i might be biased having just wrapped my head around CL.
10:59 ;)
10:59 rhickey: some Scheme's have adopted the use of [], by convention, to distinguish data lists from code lists
11:00 drewr: Aren't they synonomous with () though? I thought it was just convention.
11:00 rhickey: Yes, I did say by convention
11:00 drewr: Sorry, read too fast.
11:01 rhickey: but the reading experience is similar, although Clojure's [] are vectors
11:01 I haven't had anyone ask to go back to parens for everything :)
11:02 jteo: true. i'll get used to it i suppose.
11:04 Chouser: I really really like the use of []. I think that tiny little adjustment might be part of why I have found Clojure to be so much easier to read than other lisps.
11:04 Or perhaps I've just reached some kind of critical mass in my lisp experience. ;-)
11:04 rhickey: thanks for the binding capture hint.
11:09 rhickey: Concurrency talk video is up: http://
11:13 drewr: rhickey: Thanks for sharing these talks with the world. I've found them very helpful.
11:13 rhickey: you're welcome
12:13 Chouser: abrooks: many times when you would use 'for' and want side-effects you might be better off with 'doseq'
12:15 * rhickey considering dofor
12:18 Chouser: would that replace doseq?
12:18 rhickey: no, would replace (dorun (for ...
12:19 * Chouser nods
12:20 rhickey: or maybe doseq with [] would be that, e.g. (doseq [...] == (dorun (for [...]
12:20 e.g. add list comprehensions to doseq
12:20 Chouser: yeah, that's what I was driving at.
12:22 cgrand: how would you doseq over a map then? (doseq [k v]...
12:22 rhickey: hmmm... couldn't determine if doseq [...] xs exprs was list comprehension or destructuring...
12:22 :)
12:22 cgrand: :-)
12:23 * rhickey better think about this over lunch
12:50 rhickey: doseqs
12:57 Chouser: sure!
12:58 rhickey: 'for' could be 'from' to avoid confusing people...
12:59 and better imply sequence vs. iteration
13:00 jteo: umm, newbie question: what is the exact definition of a 'binding form'?
13:03 rhickey: fn parameter or first half of a let binding
13:03 contains symbols that will be bound to values
13:04 simplest binding form is a symbol
13:04 jteo: thanks! :)
13:05 Chouser: with the clarity of [] in doseqs for the cost of just two keystrokes, I
13:05 rhickey: but vectors and maps can be binding forms too, containing symbols that will be bound to parts of the value n a process called destructuring
13:05 Chouser: ...I'll probably stop using doseq
13:06 rhickey: hmm...
13:07 Chouser: and for what it's worth, I think I'd prefer 'for' over 'from'.
13:08 rhickey: Chouser: I did too, but I get a lot of people thinking it's iteration/loop
13:08 * abrooks comes back after lunch and sees Good Things happening. :)
13:09 abrooks: I like where this conversation is going.
13:10 Chouser: I can see that as a problem, but 'from' strikes me as weak solution.
13:10 I guess if 'for' has inaccurate connotations, picking something that has no connotations at all /might/ be better.
13:11 rhickey: what are the connotations of from that conflict?
13:11 abrooks: (comprehend ...) Hm. No.
13:12 rhickey: The verb is implied in either case, but I think people read/infer for...do and from...take
13:13 Chouser: I just meant 'from' has no specific connotations, which does help me understand when first reading it, but doesn't mislead me either.
13:13 does *not* help me understand...
13:13 bleh
13:13 I just meant 'from' has no specific connotations, which doesn't help me understand when first reading it, but doesn't mislead me either.
13:14 abrooks: seq-from?
13:14 Chouser: ew
13:14 lazy-for?
13:15 abrooks: lazy-ass? (lazy assignment :)
13:19 I kind of like lazy-for. It explicitly puts it in the class of lazy-cons and lazy-cat.
13:19 rhickey: 'from' has connotations from SQL for anyone that's used a db
13:19 abrooks: The current (for ) could be eager matching peoples expectations of iteration.
13:20 rhickey: abrooks: lazy in lazy-cons/lazy-cat refers to the evaluation of the arguments, not the laziness of the result, else most of the seq library would be lazy-this/lazy-that
13:21 abrooks: I'm trying to make all side-effect ops begin with do
13:22 Chouser: SQL's 'from' doesn't have :when or :while. I guess SQL's 'where' is like clojure/for's :when...
13:22 abrooks: do-for (dofor looks dumb).
13:22 Chouser: rhickey already named that doseqs
13:23 abrooks: And doseqs would have the decomposing bindings []?
13:23 * abrooks scrolls up ...
13:23 Chouser: abrooks: yes
13:23 abrooks: destructuring not decomposing.
13:24 rhickey: doseqs would have for syntax
13:24 doseq already does destructuring
13:28 abrooks: Hm. (doseqs ) doesn't do it for me name-wise. It's more like (for ) than (doseq ). It's the notions of (for ) and (do* ). Just a thought.
13:30 Chouser: So 'doseqs' could replace (doall (for ...)) and (doseq ...), and 'from' could replace 'for'.
13:31 abrooks: Oh, if doseqs would subsume doseq I don't have a problem with it. The above plan sounds pretty appealing.
13:32 Chouser: well, when I suggested doseq going away, rhickey said only "hmm..."
13:34 abrooks: Why not just add the syntax to doseq?
13:34 * abrooks tires to think if the additional syntax would be incompatible.
13:34 abrooks: er... ^tires^tries
13:34 I am tired, though.
13:34 More tea.
13:35 Chouser: abrooks: yes, the syntax would be incompatible.
13:38 (doseq [w x] y z) <-- is [w x] a binding form for y, or is w binding x (with y and z making up the body)?
13:38 (doseqs [[w x] y] z) vs. (doseqs [w x] y z)
13:49 'from' and 'doseqs' would have very different names considering the similarity of their syntax.
13:51 cgrand: I'd like to submit this channel for archiving to Arkivo http://
13:53 Chouser: I can't see anything other than the last 100 messages. Am I doing something wrong?
13:54 cgrand: chouser: the little non-obvious green tab "Browse Archive"
13:54 Chouser: yeah, but even there I only see today's date?
13:54 oh, some of them go back farther.
13:55 cgrand: chouser: indeed
13:55 is there another public irc archiving service?
13:56 abrooks: cgrand: None. None that Chouser knows of. [hairy eyeball at Chouser]
13:56 cgrand: (modifying the url by hand is not so fun)
13:58 Chouser: oh, if it's just a UI thing, I imagine they'll fix it.
13:59 abrooks: Chouser: Actually, I realized that there's work that would need to be done to otto and noiselog before they would really be usable outside of a #noise environment.
13:59 rhickey: cgrand: archiving would be great
13:59 Chouser: abrooks: yes. more than starting from scratch, perhaps.
14:01 abrooks: irclog.org might be a solution.
14:03 Chouser: If someone has a Java server environment they could lend, we could write a solution in Clojure.
14:03 abrooks: Oh, right, I forgot you finished noiski. :)
16:16 drewr: I'm having trouble figuring out where clojure/seq is having a problem: http://
16:17 (I'm adapting the spelling corrector to work with recent clojure.)
16:18 I isolated that snippet out of the edits1 function.
16:21 Ah, it looks like I hadn't restarted my JVM since updating my working copy.
16:26 Chouser: is it working now?
16:27 drewr: Yeah, it works. I ended up only having to change two FOR invocations.
16:27 ...to use :when.
16:27 Should I update the wiki even though this probably won't work with the released version?
16:31 Better not since the old definition is what's documented in the published API.
16:33 Chouser: You could add a comment to the end, so it'll be easy to update after the next release.
16:37 ok, I need Java help. how best to do sprintf of "%d:%02d"?
16:45 (defn fmt [h m] (str h ":" (. (new java.text.DecimalFormat "00") format m)))
16:50 (. java.text.MessageFormat format "{0,number,0}:{1,number,00}" (to-array [1,5]))
16:51 drewr: Take a look at Arto's impl.
16:51 * drewr looks for link
16:51 drewr: http://
16:52 Chouser: thanks
17:31 drewr: What did EQL? turn into?
17:32 rhickey: =
17:32 drewr: Ah.
17:38 * drewr out
20:17 Modius: Do clojure's functions have any form of TailCallOptimization?
20:19 Chouser: Modius: no, but you can use the 'recur' form to manually achieve the same performance.
20:20 Modius: Is that a code-walking macro basically?
20:20 Converting the code to cps form?
20:20 Chouser: no, I don't think so.
20:20 recur is a bit like a tail-call-optimised function call to the enclosing function (or 'loop')
20:22 See 'recur' on this page: http://
20:31 If I know I'm going to loop through an entire seq several times
20:31 ...it probably makes sense to force it to be computed once.
20:33 Is 'doall' the right way to do that, even though there are no side-effects involved?
21:16 Is 'doall' the right way "pre-fetch" a lazy seq's values, even if there are no side-effects involved?
21:19 rhickey: it's a way, why would you need to do that?
21:28 Chouser: If I know I'm going to loop through an entire seq several times, and I think it'll be cheaper to use the values than to recompute them.
21:30 oh, or does FnSeq cache the results automatically?
21:30 rhickey: yes it does
21:31 Chouser: I'm sorry, it's even documented. I'll go away now.