#clojure logs

2008-04-09

10:06ChouserShouldn't (binding [x 5] x) just return 5?
10:09drewrIt does for me.
10:09drewruser> (def x 1)
10:09drewr#<Var: user/x>
10:09drewruser> (binding [x 5] x)
10:09drewr5
10:10Chouseroh! you have to def it first.
10:11ChouserI think I used to know that. Thanks!
10:12drewrWhat I don't understand is why you can't just use let.
10:12Chouseryou can, but they do different things.
10:12Chouserlet is lexical. you can use x inside the syntactic boundaries of the (let ...)
10:12Chouserbindings survive through function calls.
10:12Chouser"dynamic binding" I think it's called.
10:13Chouser(defn prnx [] (prn x))
10:14Chouser(binding [x 5] (prnx)) --> prints 5
10:14Chouser(let [x 5] (prnx)) --> crashes, because x is not defined in prnx
10:14cgrandchouser: dynamic scoping
10:14Chousercgrand: thanks.
10:14rhickeyboth correct
10:16cgrandrhickey: thanks
10:16Chouserso shouldn't this work? (binding [x 5] (for [i [1 2]] [i x]))
10:16drewrChouser: The first defn won't succeed though.
10:16Chouserdrewr: you still have to do a (def x) earlier, like you showed me.
10:19Chouserdoes that binding...for crash for anyone else?
10:20drewrOK, looking at the definitions of print and println helps me understand how that's useful.
10:24rhickeyChouser: crash?
10:24abrooksI think he meant took an exception.
10:24Chouserwell, an exception. java.lang.IllegalStateException: Var x is unbound.
10:24Chousersorry. sloppy use of English.
10:24rhickeyremember for is lazy, better consume it all before the binding goes out of scope
10:25Chouseroh! weird...
10:25Chousera closure doesn't hang onto its dynamic scope?
10:25abrooksChouser: That one agin... :)
10:25rhickeythe seq is outliving the binding
10:25abrooksrhickey: Is the best way to (doall (for ....)) ?
10:25rhickeyclosure == lexical scope, bdingind == dynamic scope, so no
10:25rhickeybinding
10:26Chouserabrooks: I didn't realize this was the problem you were having.
10:26abrooksabrooks: That was the issue the other night. Look at the noise.log.
10:26Chouserabrooks: yeah, I thought I understood at the time, but apparently I didn't.
10:26rhickeyabrooks: dorun or doall, depending on if it's all side effects or you want to retain the seq
10:28abrooksrhickey: 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:29abrooksShould non-terminal slots in do be eager?
10:30rhickeyabrooks: no
10:30abrooksHm. For my own understanding, why? :)
10:30abrooksOr why not, actually.
10:30rhickeyI do think 'for' implies iteration for people though, so this is a common mistake
10:31abrooksYes. The imperative meme has clamped onto all of our brainstems and is quite embedded.
10:31ChouserFWIW, I'm fine with a 'for' being lazy, it was the behavior of binding and closure that threw me.
10:31rhickeyabrooks: there's not really a notion of a terminal slot, they all move together like an odometer
10:32Chouseritems in 'do' are sequential, aren't they?
10:32abrooksrhickey: In a (do ..)?
10:32abrooksI thought they were as Chouser said.
10:33rhickeyabrooks: I thought you meant for, there's no laziness in do
10:34abrooksrhickey: (do ) allows for to be lazy.
10:34rhickeyabrooks: for is always lazy
10:34abrooks(do (for [x (range 10)] (println x)) 9)
10:35abrooksrhickey: I'm probably not saying this right.
10:35abrooksIf I remove the 9 in the above, (do ) consumes all of the for. In the non-terminal slot, it doesn't.
10:36rhickeyabrooks: no, the repl is what consumes the for, in printing the result
10:36abrooks(do (for [x (range 10)] (println x)))
10:36rhickey (def x (do (for [x (range 10)] (println x))))
10:36rhickeyx
10:37abrooksAh. And in the general case, /something/ is consuming the last value of (do ).
10:37rhickeymaybe
10:38abrooksThe sticking point for me is that the values of other slots of do are thrown away and are never consumed, right?
10:38rhickeyright, do is for side effects
10:38abrooksSo if do is for side effects then should it be eager?
10:38abrooksAt least for non-terminal slots?
10:39abrooks^should it^shouldn't it
10:39rhickey(do (foo) (bar) (baz))
10:39rhickeyhow does do know if foo returns a lazy seq that needs forcing?
10:40abrooksShould 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:40drewrrhickey: 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:40rhickeyChouser: you can use a dynamic value in an expression that returns a lazy seq by capturing it:
10:41drewrFor example, this conversation would be much clearer if we could write DOALL, FOR, etc.
10:41rhickey(def x 1)
10:41rhickeyuser=> (binding [x 5] (for [i [1 2]] [i x]))
10:41rhickey([1 5] [2 1])
10:41rhickeyuser=> (binding [x 5] (let [x x] (for [i [1 2]] [i x])))
10:41rhickey([1 5] [2 5])
10:42abrooksdrewr: I'm case insensitive. I was born that way. The doctors think it's my brain not my eyes.
10:42rhickeydrewr: I consider CL's treatment of case a major misfeature
10:43drewrrhickey: Scheme is case-insensitive too.
10:43drewrabrooks: That's an argument for case-insensitivity. :-)
10:43abrooksdrewr: In conversation it can be fine (and clear) to type bare language constructs upper-case.
10:45abrooksdrewr: I think the best argument for case sensitivity is that it forces other people's code to look the same.
10:45rhickeycase insensitivity is information-lossy
10:45rhickeycan be a huge problem when identifiers have to go through Lisp in/out of the outside world
10:45rhickeythink about Clojure's java interop
10:47drewrThat'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:47drewrI buy that.
10:48drewrAlthough, as a personal preference, I tend to like CL and Scheme's case agnosticism.
10:48rhickeyheh - one of my number one problems with CL
10:51jteoimho, worth the price for java interop.
10:51drewrjteo: Yeah, I agree.
10:53drewrI 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:53rhickeyI simply think it's wrong for the user to enter x and the system to change it to X, so ascii, so 1970s...
10:54rhickeygreatly reduces the utility of symbols
10:55rhickeyjava interop/natural language/xml
10:56jteominor nitpick: i'm confused by the use of "[ ]". :)
10:56rhickeyconfused in what way?
10:57jteoas opposed to common lisp, where you would only ever see "( )" encompass variables.
10:58rhickeyI find Clojure much easier to read than CL
10:59jteoi admit i might be biased having just wrapped my head around CL.
10:59jteo;)
10:59rhickeysome Scheme's have adopted the use of [], by convention, to distinguish data lists from code lists
11:00drewrAren't they synonomous with () though? I thought it was just convention.
11:00rhickeyYes, I did say by convention
11:00drewrSorry, read too fast.
11:01rhickeybut the reading experience is similar, although Clojure's [] are vectors
11:01rhickeyI haven't had anyone ask to go back to parens for everything :)
11:02jteotrue. i'll get used to it i suppose.
11:04ChouserI 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:04ChouserOr perhaps I've just reached some kind of critical mass in my lisp experience. ;-)
11:04Chouserrhickey: thanks for the binding capture hint.
11:09rhickeyConcurrency talk video is up: http://clojure.blip.tv/file/812787
11:13drewrrhickey: Thanks for sharing these talks with the world. I've found them very helpful.
11:13rhickeyyou're welcome
12:13Chouserabrooks: many times when you would use 'for' and want side-effects you might be better off with 'doseq'
12:18Chouserwould that replace doseq?
12:18rhickeyno, would replace (dorun (for ...
12:20rhickeyor maybe doseq with [] would be that, e.g. (doseq [...] == (dorun (for [...]
12:20rhickeye.g. add list comprehensions to doseq
12:20Chouseryeah, that's what I was driving at.
12:22cgrandhow would you doseq over a map then? (doseq [k v]...
12:22rhickeyhmmm... couldn't determine if doseq [...] xs exprs was list comprehension or destructuring...
12:22rhickey:)
12:22cgrand:-)
12:50rhickeydoseqs
12:57Chousersure!
12:58rhickey'for' could be 'from' to avoid confusing people...
12:59rhickeyand better imply sequence vs. iteration
13:00jteoumm, newbie question: what is the exact definition of a 'binding form'?
13:03rhickeyfn parameter or first half of a let binding
13:03rhickeycontains symbols that will be bound to values
13:04rhickeysimplest binding form is a symbol
13:04jteothanks! :)
13:05Chouserwith the clarity of [] in doseqs for the cost of just two keystrokes, I
13:05rhickeybut 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:05Chouser...I'll probably stop using doseq
13:06rhickeyhmm...
13:07Chouserand for what it's worth, I think I'd prefer 'for' over 'from'.
13:08rhickeyChouser: I did too, but I get a lot of people thinking it's iteration/loop
13:09abrooksI like where this conversation is going.
13:10ChouserI can see that as a problem, but 'from' strikes me as weak solution.
13:10ChouserI guess if 'for' has inaccurate connotations, picking something that has no connotations at all /might/ be better.
13:11rhickeywhat are the connotations of from that conflict?
13:11abrooks(comprehend ...) Hm. No.
13:12rhickeyThe verb is implied in either case, but I think people read/infer for...do and from...take
13:13ChouserI just meant 'from' has no specific connotations, which does help me understand when first reading it, but doesn't mislead me either.
13:13Chouserdoes *not* help me understand...
13:13Chouserbleh
13:13ChouserI just meant 'from' has no specific connotations, which doesn't help me understand when first reading it, but doesn't mislead me either.
13:14abrooksseq-from?
13:14Chouserew
13:14Chouserlazy-for?
13:15abrookslazy-ass? (lazy assignment :)
13:19abrooksI kind of like lazy-for. It explicitly puts it in the class of lazy-cons and lazy-cat.
13:19rhickey'from' has connotations from SQL for anyone that's used a db
13:19abrooksThe current (for ) could be eager matching peoples expectations of iteration.
13:20rhickeyabrooks: 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:21rhickeyabrooks: I'm trying to make all side-effect ops begin with do
13:22ChouserSQL's 'from' doesn't have :when or :while. I guess SQL's 'where' is like clojure/for's :when...
13:22abrooksdo-for (dofor looks dumb).
13:22Chouserrhickey already named that doseqs
13:23abrooksAnd doseqs would have the decomposing bindings []?
13:23Chouserabrooks: yes
13:23abrooksdestructuring not decomposing.
13:24rhickeydoseqs would have for syntax
13:24rhickeydoseq already does destructuring
13:28abrooksHm. (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:30ChouserSo 'doseqs' could replace (doall (for ...)) and (doseq ...), and 'from' could replace 'for'.
13:31abrooksOh, if doseqs would subsume doseq I don't have a problem with it. The above plan sounds pretty appealing.
13:32Chouserwell, when I suggested doseq going away, rhickey said only "hmm..."
13:34abrooksWhy not just add the syntax to doseq?
13:34abrookser... ^tires^tries
13:34abrooksI am tired, though.
13:34abrooksMore tea.
13:35Chouserabrooks: yes, the syntax would be incompatible.
13:38Chouser(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:38Chouser(doseqs [[w x] y] z) vs. (doseqs [w x] y z)
13:49Chouser'from' and 'doseqs' would have very different names considering the similarity of their syntax.
13:51cgrandI'd like to submit this channel for archiving to Arkivo http://irclog.turbogears.org/ Are you okay with that?
13:53ChouserI can't see anything other than the last 100 messages. Am I doing something wrong?
13:54cgrandchouser: the little non-obvious green tab "Browse Archive"
13:54Chouseryeah, but even there I only see today's date?
13:54Chouseroh, some of them go back farther.
13:55cgrandchouser: indeed
13:55cgrandis there another public irc archiving service?
13:56abrookscgrand: None. None that Chouser knows of. [hairy eyeball at Chouser]
13:56cgrand(modifying the url by hand is not so fun)
13:58Chouseroh, if it's just a UI thing, I imagine they'll fix it.
13:59abrooksChouser: 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:59rhickeycgrand: archiving would be great
13:59Chouserabrooks: yes. more than starting from scratch, perhaps.
14:01abrooksirclog.org might be a solution.
14:03ChouserIf someone has a Java server environment they could lend, we could write a solution in Clojure.
14:03abrooksOh, right, I forgot you finished noiski. :)
16:16drewrI'm having trouble figuring out where clojure/seq is having a problem: http://paste.lisp.org/display/58904
16:17drewr(I'm adapting the spelling corrector to work with recent clojure.)
16:18drewrI isolated that snippet out of the edits1 function.
16:21drewrAh, it looks like I hadn't restarted my JVM since updating my working copy.
16:26Chouseris it working now?
16:27drewrYeah, it works. I ended up only having to change two FOR invocations.
16:27drewr...to use :when.
16:27drewrShould I update the wiki even though this probably won't work with the released version?
16:31drewrBetter not since the old definition is what's documented in the published API.
16:33ChouserYou could add a comment to the end, so it'll be easy to update after the next release.
16:37Chouserok, I need Java help. how best to do sprintf of "%d:%02d"?
16:45Chouser(defn fmt [h m] (str h ":" (. (new java.text.DecimalFormat "00") format m)))
16:50Chouser(. java.text.MessageFormat format "{0,number,0}:{1,number,00}" (to-array [1,5]))
16:51drewrTake a look at Arto's impl.
16:51drewrhttp://svn.bendiken.net/clojure/util.clj
16:52Chouserthanks
17:31drewrWhat did EQL? turn into?
17:32rhickey=
17:32drewrAh.
20:17ModiusDo clojure's functions have any form of TailCallOptimization?
20:19ChouserModius: no, but you can use the 'recur' form to manually achieve the same performance.
20:20ModiusIs that a code-walking macro basically?
20:20ModiusConverting the code to cps form?
20:20Chouserno, I don't think so.
20:20Chouserrecur is a bit like a tail-call-optimised function call to the enclosing function (or 'loop')
20:22ChouserSee 'recur' on this page: http://clojure.sourceforge.net/reference/special_forms.html
20:31ChouserIf I know I'm going to loop through an entire seq several times
20:31Chouser...it probably makes sense to force it to be computed once.
20:33ChouserIs 'doall' the right way to do that, even though there are no side-effects involved?
21:16ChouserIs 'doall' the right way "pre-fetch" a lazy seq's values, even if there are no side-effects involved?
21:19rhickeyit's a way, why would you need to do that?
21:28ChouserIf 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:30Chouseroh, or does FnSeq cache the results automatically?
21:30rhickeyyes it does
21:31ChouserI'm sorry, it's even documented. I'll go away now.