#clojure logs

2008-07-25

03:12meredyddChouser: A-ha.
03:12meredyddChouser: I had no idea what you were talking about, until I grepped the API document for ":state"
03:13meredyddand realised that what I thought was part of the paragraph about factory methods was in fact a description of another option.
08:32meredyddHey...does the Java interop work with Java var-arg methods?
08:33rhickeythere are no real var-arg methods in Java, they take arrays and, for now, to call them you have to pass arrays
08:34meredyddI'm aware that they're arrays behind the scenes
08:34meredyddI take it there's no tag you can examine to see who is and who isn't a var-arg method?
08:36rhickeythere is, the problem is that Java uses types to detect the difference between passing an array (to match the array arg) and passing a non-array (which Java will turn into an array auto-magically)
08:38rhickeyso it's (String/format "%d%d%d" (to-array [1 2 3])) for now
08:55Chouserprobably warrants a mention on the java-interop page
09:02cemerickan impl of defbean (now called genbean) that I'm mostly happy with is finally done, along with a generalized approach for integrating it (and other gen-and-save-class usage) into a build process; hopefully, I'll get to writing it up for the group later today
09:03rhickeycemerick: cool, is there something you still wish you had for that?
09:04cemerickrhickey: not much, aside from the ability to define method impls in a gen-class body
09:05cemerickI ended up ditching the proxy approach entirely because invoking the polymorphic "makeNew" function was way too cumbersome
09:07cemericka small thing would be to have a *verbose-gen-class* (or whatever) var that would println where gen-and-save-class is trying to save bytecode
09:09lisppaste8rhickey pasted "group-by partition-by" at http://paste.lisp.org/display/64190
09:10cemerickrhickey: oh, right the rumored, forthcoming name munging in gen-class would be *really* helpful in general
09:19rhickeyChouser: I think partition-by is a better name for what you were trying to do
09:20rhickeythe version I pasted call f once per item
09:30Chouseryeah, group-by sound enough like relation-speak that it's better working on sets or maps.
09:31Chouserok, very clever use of "identical?" on a lazy seq
09:34Chouserf gets called one extra time on the first item of each partition, doesn't it? for fv?
09:35rhickeycould be drop-while ... (rest s) I guess, to avoid that
09:36Chouserah, yep.
09:37lisppaste8rhickey annotated #64190 with "partition-by with no redundant calls" at http://paste.lisp.org/display/64190#1
10:03lisppaste8blackdog pasted "no matching field?" at http://paste.lisp.org/display/64193
10:04blackdoghi can someone tell me why i get a no matching field exception
10:04blackdogplease
10:05rhickeyblackdog: Woot doesn't derive from anything that has an actionPerformed method. You can't add methods by just putting them in the Clojure side
10:05blackdogoh,
10:06blackdogok, i thought gen- classes were much more general than proxy,
10:07rhickeyblackdog: they are, but you still have to make sure your methods are in the Java class itself, either by deriving or using the :methods argument to gen-class
10:08rhickeyJava class signatures are not dynamic
10:08blackdogis there any way then to create a new class with some methods totally in clojure?
10:09blackdogi'm trying to attach some handlers to a gui designer, and it's looking for an object with actionPerformed methods
10:10rhickeythe gen-class system partitions class definition into 2 parts - the part Java requires be static, i.e. the signature, and everything I can make dynamic (the implementation)
10:10rhickeythe gui designer is looking for an instance of java.awt.event.ActionListener, no?
10:11blackdogwell. it
10:11blackdogit's a runtime lib (jformdesigner) that reads xml descript
10:11blackdogand then you simply say setTarget(handlerobject)
10:11blackdogso i'm trying to setup the handler object
10:11blackdogin clojure
10:12blackdogthe handler object is a pojo
10:12blackdogwith just the correct methods names
10:13blackdogso i don't have anythign to derive from, but maybe i should investigate further the runtime api
10:13blackdogit may have more,
10:13rhickeywell, you can proxy ActionListener, gen-class ActionListener, or gen-class :methods ... actionPerformed ...
10:14blackdogok, i'll go off and think about that, thanks rhickey
10:24blackdogrhickey, gen-class :methods allows one to define the static part then?
10:25rhickeyblackdog: everything in the gen-class defines the static part, but the :methods are just signatures. The definition still goes in the Clojure code as you had it
10:26blackdogbut does the :methods get around having to derive or implement something - sorry for my denseness
10:27rhickeyright, :methods are in addition to anything you get by deriving
10:27blackdogok good, so that should work for me then
10:28blackdogha! lift-off
10:29blackdogthanks!
10:29rhickeysure
14:58cemerickach! why doesn't Google Groups support at least 80-column text? :-/
14:59cemerickach! why doesn't Google Groups support at least 80-column text? :-/
15:00rhickeycemerick: yeah, if you have something substantial, you can attach it
15:01cemerickrhickey: where? I don't see any way to attach a file to a post. Or, do you mean upload it to the files section of the group?
15:01Chouseryou may need to post via email, and attach to your email
15:01rhickeywhat he said
15:02cemerickah. I should have done that.
15:03rhickeycemerick: you can still
15:04cemerickYeah, I suppose I'll repost. It'll create a new thread, though, yes?
15:04rhickeyor you can follow up to your original message with a short note and the attached file
15:07cemerickah, I'll delete the original and send an email
15:13cemerickmuch better
15:22rhickeycemerick: a couple of thoughts, using the current ns as a name is very troubling - I know that's on me to provide defs of qualified names
15:22rhickeyas far as get/set, setProperty is a problem - while it would be familiar looking, it won't be familiar behaving, as it doesn't modify the object in place.
15:26rhickeyanyone want to take a crack at gen-interface? should be really easy, learn a little bytecode gen?
15:30cemerickrhickey: using the current namespace for the method impls and classname certainly isn't "hygenic", but that's what the typical usage would be anyway
15:31cemerickI don't mind at all having a setProperty that returns a new Foo, rather than having mutable semantics. That might freak out some Java/.NET people, but that's better than having broken equals semantics.
15:31Chousergen-interface would take a single class, no options, and do the minimal gen-class equivalent for it?
15:31rhickeyChouser: no, allow the definition of an interface from scratch, just signatures
15:31ChouserI was thinking I might poke at gen-class function name mangling if nobody beat me to it.
15:32Chouserah.
15:34rhickeyChouser: if '.' prefix is too clever, what about '-' ?
15:35rhickeyother genclassers please chime in
15:35ChouserI was thinking I'd do something lengthy (and internally configurable), and just provide a def-gen-method to match the same mangling.
15:36cemerickwe're talking about mangling names so as to avoid the name clashes with referred namespaces?
15:36rhickeycemerick: yup
15:36Chouserat least that would could be done now safely, and allow any code written using it to be forward compatible with any more minimal mangle that might be chosen later.
15:36Chousers/would//
15:37cemerickI'd definitely avoid '.' as a prefix. A '-' prefix would be a 99% solution, certainly.
15:37rhickeythe problem with a mangle hidden by a special def is - how do you call/test it? It's still a normal function
15:37Chouseri'd be worried (defn -foo) looks a lot like (defn- foo)
15:39Chouseryou might need to have "this" bound when you call it manually, right? there aren't any other special rules?
15:39rhickeymaybe, but both are implementation details, editor coloring clears up pretty well
15:39cemerickI've always liked the python convention of a double-underscore *shrug*
15:39rhickeyChouser: yes this, no, they are regular fns
15:39rhickeycemerick: Lisp uses - instead --method would be ok too
15:39Chouserbut you could test by creating an instace of the class and calling them as methods -- that would get "this" right, and follow any mangling.
15:40Chouserpython uses double-underscore surround the name, which makes it hard to say aloud: __foo__
15:40cemerickrhickey: yeah, I was just replying to Chouser's concern about a prefixed '-' appearing too similar to defn-
15:40ChouserI guess "dash dash foo dash dash" is a bit better.
15:40rhickeyas methods they are less powerful than fns, not first-class
15:40rhickeycan't map etc
15:41rhickeyChouser: we have to stay off the end, already used for types
15:41Chouserah, right. ok, so dump def-gen-method, and we'll just finish this mangling detail discussion right now. :-)
15:41cemerickChouser: actually, "private" names in python usually have double-underscore only in front of the name -- that's what triggers name mangling
15:41Chousercemerick: oh! ok.
15:42ChouserI'm fine with a -- prefix. *shrug*
15:42Chouseror a .. prefix, or #! or whatever. ;-)
15:43cemerickyeah, I really don't think it matters, outside of not using '.'. :-)
15:45cemerickactually, '-' sorts ahead of most other chars, which would be unfortunate for tools, etc.
15:46rhickeyanother potential issue with -- is it get munged to __, which is a name component I presume the Clojure implementation "owns"
15:46Chouserwe don't really want anything starting with # since that triggers reader magic, right?
15:46cemerickpipes would work, and they sort after all other ascii chars; not so pretty, tho
15:46rhickeyChouser: right!
15:46Chouser* mean "global"
15:46Chouser% is already taken
15:47rhickeyI'm reserving all other special chars
15:47Chouser@ and ~ are already taken pretty globally as well, right?
15:47Chouseroh. so it has to be -, ., or alphanumeric?
15:47rhickeythis isn't worth a special character
15:48Chouserand since I think a prefix makes a lot of sense (compared to a postfix), it's really just alpha.
15:48Chouser-- is apparently dangerous, so either just "-" or something like "method-" or "gen-"
15:49cemerickwell, these names aren't going to be accessed with any kind of regularity, right?
15:49Chouserthe only other requirement being that it is very unlikely for a Java class to use in a normal method name.
15:49cemerick(by non-generated code, I mean)
15:49rhickeyI'm not sure sorting first is bad, when looking at a ns dedicated to a class implementation, the methods will sort first
15:53Chouserany kind of prefix will have them sorted together. Having them first seems a little nicer than having a bunch of "method-*" between your "loo" and your "noo" functions.
15:53rhickeycemerick: right, the names might only rarely be used
15:54Chouser"-m-" prefix
15:54cemerickChouser: +1
15:54Chouserthat would sort first, stand out more than just "-", suggests a method without being verbose
15:55Chouserand if that gets mangled to "_m_" I think we've avoided better than 99.9% of Java method names.
15:56rhickeyChouser: the only conflict with - is if a class defined public foo and _foo, even then, one becomes _foo and the other __foo
15:57rhickeyalpha prefixes dramatically reduce readability imo, - disappears, but m doesn't
15:58ChouserI agree - is technically sufficient, I'm just not convinced the difference between (defn- foo) and (defn -foo) is unmistakable.
15:58Chouserhm.
15:59rhickeyin my editor defn- foo is all black and defn -foo is purple/blue
16:02rhickeyericthor: any thoughts if you are there? (enclojure might have more genclass than anyone)
16:07rhickeyor we could use _, to remind us we're in Java-land
16:07rhickey(defn- foo (den _foo
16:08rhickey(defn- foo (defn _foo
16:17Chouserworks for me, but either is fine.
16:18rhickeyon an unrelated note: (derive java.util.Collection `aggregate) will work
16:19rhickeyi.e. superimpose your own taxonomy on existing classes
16:40mebaran151__is there a good way to get an arbitrary hash for an arbitrary object that would ensure uniqueness on value: I'd like to use this string representation for a primary key functionality in an app i'm writing
16:42Chousersounds like you want sha1 or md5
16:51mebaran151__for like a whole map though?
16:52mebaran151__like I'd like to be able to just take a random hashmap I created in clojure and run a function on it to return a string
16:52mebaran151__that would be unique over the values of that hash
16:52mebaran151__internally, that must be how clojure handles equality I would think
16:55Chouserwhole maps have a hash value, but there's no guarantee they're unique -- when placed in a map or set a value comparison needs to be done to make sure you've really got the right item
16:55ChouserI think. That's normal for hashes, though.
16:56ChouserFor equality you can use "identical?", but that'll give you false negatives. To be sure, I think the whole collection is compared.
16:58mebaran151yeah
16:58Chouserso if you want a guaranteed-unique hash, I think you'd have to use md5 or sha1 on the whole value.
16:59mebaran151it's a cool little project: trying to layer a fs db written in clojure
16:59mebaran151I might just go with my old idea of incrementing a string
16:59ChouserIf the value is made up of just well-printable clojure objects, you could print to a string and run sha1 on it.
17:00mebaran151oh that's actually decent idea
17:00mebaran151yes
17:00mebaran151most of the objects will be well printable
17:00mebaran151I'm actually planning on internally bucketing the objects via their printed forms anyway
17:19Chouserwoo! I've been stabbing in the dark, and finally hit my target. Now I just have to understand it...
17:20rhickeyChouser: what target?
17:20Chouserprepending a - on function names but not method names. ;-)
17:20ChouserIt's taken me, what, an hour? It would have taken you 15 seconds.
17:21ChouserI'm trying to find where we discussed before which names you wanted mangled and which you wanted to leave alone.
17:21rhickeyChouser: ah, yeah, it's a bit thick in there
17:21Chouserheh. yeah. But I don't know a better way to learn it.
17:23Chouserah, here it is. "the names manually given to genclass would remain unmunged? :factory, :state, etc?"
17:25rhickeyI don't know, seems like the same arguments might apply - these names are dictated by outside requirements and could just as easily bang into clojure names - prefixed with _ they never would
17:25rhickeydoing them all is probably way easier
17:26Chouseryeah. doing them all is (maybe?) done.
17:26rhickeycool!
17:26Chouserbut not all the names are dictated -- init, state, etc.
17:26rhickeystate is a field
17:27Chouseroh, "public". ok.
17:27rhickeyI think it will be easiest for users too, to know the rule is clojure implementations of Java gen methods begin with _
17:28rhickey?
17:28rhickeypublic?
17:28ChouserI knew :state was a field, but I didn't realize it was public.
17:28rhickeyyes, public and final, so no getter/setter
17:30Chouserwell, maybe I'm completely missing something (seems likely), but my change is to replace genclass line 276: (. gen push (str "_" v))
17:30Chouserseems to work as expected.
17:31Chouserperhaps I need to test ctors, factories, etc.
17:32rhickeywhat about the lookup side?
17:33rhickeyline 187?
17:35blackdogi'm trying to define a function defn as the body part of a macro
17:36blackdogand then using that as part of gen-and-load-class
17:36blackdogdefinition, but the function name has a _var appended
17:36blackdog[['wootActionPerformed [ActionEvent] Object]]
17:37blackdogCaused by: java.lang.ClassFormatError: Illegal field name "user/wootActionPerformed__var" in class igw/forms/Woot
17:37blackdogis that just a dumb thjing for me to try?
17:38rhickeyblackdog: want to paste your macroexpansion?
17:38blackdogoh, i'll try, haven't really used that
17:38blackdogdo i just stick macroexpand around the macro call?
17:39rhickeyif you are having a macro problem, macroexpand is the first thing you should try, stick macroexpand around the *quoted* call
17:39rhickey(macroexpand '(my-macro x y z))
17:39blackdogok
17:40rhickeyif your macro expands into another macro, try macroexpand-1 first
17:42blackdogis there a pretty print for a macro?
17:42blackdogmacroexpand?
17:42rhickeyno pprint yet
17:42blackdogk
17:42rhickeyemacs?
17:43blackdogno, i'm using jedit :(
17:44lisppaste8blackdog pasted "macroexpand" at http://paste.lisp.org/display/64223
17:45blackdogi don't see _var in the macroexpand
17:46lisppaste8blackdog pasted "stacktrace" at http://paste.lisp.org/display/64225
17:47blackdogthe methods section in the macro itself is hard coded, would be replaced
17:48rhickeyuser/wootActionPerformed is not a valid method name, you have to generate an unqualified name
17:48rhickeythe __var is added by the implementation of gen-class, but is not the problem
17:50blackdogin the macro it tries to do (in-ns ~kls) to set the ns before doing the defn of wootActionPerformed
17:50rhickeythat's not going to work
17:50blackdogok,
17:52blackdogbecause i;'m missing something fundamental or just that it's a daft thing to do?
17:54rhickeyactually, I'm not sure what you are trying to do, but one trick is to fix your expansion by hand and see if it works before fixing the macro. Always start a macro with a by-hand implementation of the expansion that works, then tweak the macro until it expands to the same thing
17:55blackdogok thanks for that,
17:55rhickeytrying to get a macro and the expanded logic right at the same time is a recipe for pain
17:55blackdogok
18:20Chouserrhickey: don't feel you need to walk me through this -- it'd probably be easier for you to just do it yourself. But if you want to answer my questions instead...
18:21ChouserIf I mangle line 187 my tests fail.
18:22Chouseris it doing a lookup in the class there? I don't want to mangle that, of course.
18:48rhickeyChouser: I see - you are not changing the names of the static fields, just the var symbols - then you don't need line 187 changed
19:04arohnerwhy can't I peek at a range?
19:04arohneruser=> (peek (range 1 10))
19:04arohner(Peek (range 1 10))
19:04arohnerjava.lang.ClassCastException: clojure.lang.Range
19:04arohnerjava.lang.ClassCastException: clojure.lang.Range
19:04arohner at clojure.lang.RT.peek(RT.java:454)
19:04arohner at clojure.fns.clojure.peek__398.invoke(boot.clj:757)
19:04arohner at clojure.lang.AFn.applyToHelper(AFn.java:184)
19:06arohneruser=> (peek '(1 2 3 4 5 6 7 8 9 10))
19:06arohner(peek '(1 2 3 4 5 6 7 8 9 10))
19:06arohner1
19:17Chouserpeek is for lists, vectors, and queues. For generic seqs, you can just use first.
19:18Chouser(first (range 1 10))
19:18arohnerok
19:18arohnerwhat is the difference between a seq and a list?
19:19Chouseroh, apparently peek is defined on IPersistentStack, which is implemented by list, vector and queue.
19:19Chouserarohner: that's a great question with a subtle answer.
19:20arohneryeah, I saw the IPersistentStack cast
19:20arohnerthat explained the stack trace, but didn't help me understand the issue :-)
19:20Chouserseq is an interface, specifically ISeq. Every ISeq provides "first" and "rest"
19:21Chouserevery collection in clojure can viewed through a seq. For example: (seq {:a 1, :b 2})
19:22ChouserA list (PersistentList) is a concrete data structure, a singly-linked list. I happens to provide the ISeq interface itself directly, unlike most other collections.
19:23Chouseruser=> (def x (list 1 2 3))
19:23Chouseruser=> (identical? x (seq x))
19:23Chousertrue
19:23Chouseruser=> (def y {:a 1, :b 2})
19:23Chouseruser=> (identical? y (seq y))
19:23Chouserfalse
19:24arohnerok, so the simple answer is that peek and pop are defined on things that have a stack interface
19:24Chouserright
19:28arohnerthanks for the help
19:29Chousernp
19:51mebaran151_is it possible to join a lazy sequence to non-lazy sequence
19:53mebaran151_I want to do something like join at the head of list (1 2 3) to an infinite sequence of 4's for instance
19:54mebaran151_in the repl, lazy-cons produced the infinite sequence I didn't want it to do
19:55Chouserthe repl will try to print all of a seq, lazy, infinite, or otherwise.
19:56Chouser(take 10 (lazy-cat (list 1 2 3 4) (repeatedly #(identity 4))))
19:57ChouserI'm not sure what the best way is to create an infinite seq of 4
19:57Chouser(take 10 (lazy-cat (list 1 2 3 4) (cycle [4])))
19:58Chouserah!
19:58Chouser(take 10 (lazy-cat (list 1 2 3 4) (repeat 4)))
20:26arohneris there a library call that gives me all of the permutations of two lists?
20:27Chouseraren't permutations usually figured from a single list?
20:27arohnerI want to pass two lists (range 1 10) (range 1 10) and get a list of tuples (1 1) (1 2) ... (10 9) (10 10)
20:27Chouserah. for
20:27arohnermaybe I'm using the wrong term
20:27slavathe cartesian product of two lists?
20:27mebaran151_thanks Chousefr
20:28Chouser(for [x (range 10) y (range 10)] [x y])
20:28arohnerah, thanks
20:28mebaran151_hey Chouser, how can I tell if my recursion is occurring in the tail position
20:28arohnerif you use (recur) it will be in the tail position, or you get an exception
20:28Chouserif the compiler lets you use (recur), then it's tail position.
20:29mebaran151_I'm trying to call recur inside an if conditional but clojure continually complaines
20:29Chouserwhat he said.
20:29slavawhy is recur in non-tail position prihibted?
20:30mebaran151_(def next-id (fn this
20:30mebaran151_ ([id] this (this id *max*))
20:30mebaran151_ ([id max] (loop [i id m max]
20:30mebaran151_ (if (< (first i) (first m))
20:30mebaran151_ (conj (incr (first i)) (rest id))
20:30mebaran151_ (conj (base (first i))
20:30mebaran151_ (recur (rest i) (rest m))))))))
20:30mebaran151_(sorry about the flood)
20:30slavamebaran151_: recr is not in tail position there because its result is passed to conj
20:30mebaran151_ah
20:30slavabut i don't understand the limitation
20:30arohnerbecause recur guarantees the stack size will not grow
20:30mebaran151_so how would I refactor this
20:31slavai'm not sure why you'd have recur at all
20:31mebaran151_well I'm recursively calling next-id
20:31slavaso just call it explicitly i guess
20:31mebaran151_my id's are basically a seq of integers
20:31mebaran151_that can be of arbitrary length
20:31arohnermebaran, you probably need a loop position inside your ([id max]) case
20:32mebaran151_it's there
20:32arohneroh, right
20:32mebaran151_maybe there's a better way about it using reduce in some fancy way
20:33arohneryou can self-call without the recur as well, you just aren't guaranteed the stack size won't grow
20:33mebaran151_I'm trying to basically do carry addition
20:33slavaso is recur just an assertion basically that has no effect on the compiled code?
20:33slavahow do you assert that a tail call to another function is a tail call?
20:33arohnerno
20:34arohnerthe explanation I've heard is that the JVM doesn't have the opcodes to do a real tail call
20:34arohnerrecur only goes to designated places in your own function
20:34arohnera (loop), the top of the function, and a few other places
20:35arohnerrecur target is the term I'm looking for
20:35slavaoh, right
20:35slavathe JVM can't tail call, I forgot about that
20:36slava you can just do a goto within the current method
20:38Chouserslava: right, that's what recur does under the covers.
20:38Chouserwhich is why it has to be in tail position.
20:39arohnerso I have a for loop that looks like
20:39arohner(for [x (range 1000)
20:40Chouser"on lisp" has a section which is where I learned how to move recursion to tail position.
20:40arohner(for [x (range 1000)
20:40arohner y (range 1000)]
20:40arohner (if foo (print "foo") nil))
20:40arohnerwhen I evaluate that, the screen is filled with prints to nil
20:41arohneris there a way to not print all the nils?
20:41Chousermebaran151_: instead of returning your accumulating value, pass it forward to the next recursive call, and finally return the whole thing at the end.
20:42mebaran151_I'm doing something similar with reduce right now
20:42slavathat's something that the compiler should do though, not hte programmer
20:42mebaran151_I agree with slava here
20:42Chouserarohner: you're trying to program for side-effects, which will be fighting uphill in clojure. What are you trying to return?
20:43slavaif the result of the non-tail-recursive call is the input to an associative operation, then its pretty easy to convert it to use an accumulator
20:43mebaran151_oh I'm trying to transform an array of ints as follows
20:43slavaif its the input to cons, you convert it to an accumulator and reverse the list at the end
20:43slavapretty simple transformation to make
20:43slavathe problem with doing it by hand is that its error-prone and you get a proliferation of auxilliary functions
20:44mebaran151_no int can be greater than the max value, and I'm incrementing from the left
20:44arohnerah, figured it out
20:44arohner:while
20:46arohnerah, I should be using :when and :while
20:46arohnerI'm not really programming for side effects, I was just being lazy because I only cared about the last value
20:46arohnerdoing project euler stuff, so I just needed to see the last value and type it in
20:49Chouserslava: I'd be interested to see a patch to Clojure that does that.
20:52Chouserarohner: yeah, I just meant with "print". project euler is a great way to learn a new language.
21:03mebaran151my method didn't work: how would you transform my example?
21:09Chouserincr is the same as inc?
21:09Chouseroh, incr and base are your own?
21:10mebaran151yeah
21:10mebaran151it's a string incrementer of my own devising
21:11mebaran151kind of like Ruby's
21:16Chouserwhat does next-id return? I'm guessing a list?
21:17rhickeyChouser: a patch to Clojure that does what?
21:17Chouserdoes tail-call optimization at compile time.
21:17rhickeyon a self-call?
21:18Chouserno, I kinda like the tail-position assertion of "recur". For non-tail-position and mutual-recursion cases.
21:19ChouserI think that's what slava was talking about, anyway.
21:19rhickeythe JVM can't do mutual recursion TCO
21:20ChouserYeah, I know. My understanding of what slava was saying is that the compiler could overcome the JVM's runtime weakness there.
21:20rhickeyIt can't
21:20rhickeyI think he was just talking about not needing recur on self-call
21:21Chouserself-call in a non-tail position?
21:21rhickeyself-call in tail position
21:21Chouseryeah, that's not interesting. :-)
21:22rhickeythe reason that I don't is because of the expectation it creates among Scheme programmers
21:24rhickeythis way it's easy to explain - there's no TCO, only recur is guaranteed non-stack-consuming
22:08slavaChouser: i was talking about an optimization that converts non-tail-calls into a tail call with an acculuator
22:08slavaeg, (defun (fac x) (if (< x 3) x (* (fac (- x 1)) x)))
22:08slavathis is not tail recursive
22:08slavabut its easy to turn it into a tail recursive function
22:12slavapeople will expect a lisp compile to do this, so it will be surprising to many if clojure doens't
22:12slavathey'll write fnctions that blow the stack without realizing it
22:21Chouserslava: are you working on a patch?
22:23ChouserIs it common for CL or Scheme to optimize non-tail calls? I haven't gotten that impression from the little reading I've done.
22:34Chousercan you guarantee all self-calls would be converted to tail-call? If not, that could cause even more surprising behavior.
22:37albinoI doubt he's working on a patch, he has his own language to contend with
22:38Chouserah
22:42slavaChouser: you can't convert all calls into tail calls of course
22:42slavaits surprising inasmuch as any compiler optimization is
22:43slavabut that's not an argument for non-optimizing compilers :)
22:44Chouserwell if the difference between optimizing and not is a bit of speed, that's one thing. If it's the difference between blowing the stack and crashing or not, that kinda matters...
22:45slavadoes java crash when you exceed a fixed-size call stack allocation or does it grow the stack?
22:46slavai haven't done any java since 1.4 or so, i guess many things have changed
22:47Chouserif I do infinite recursion, it crashes
22:47Chouser((fn x [] (x)))
22:47Chouserboom
22:47slavabecause it fills up the heap?
22:48albinoslava: how could one tell the difference?
22:49slavaif the stack has a fixed size, then converting list operations to tail recursion with a list accumulator will be a win
22:49slavaotherwise, not so much
22:50slavain both cases converting arithmetic to tail recursive form is a win because you'll run in O(1) space and not O(n)