Thank you Andy - This was fabulously helpful - I really appreciate 
your explanation.

Would you permit me to include your answer in a blog post about the above 
question?



On Monday, November 19, 2012 6:25:30 PM UTC-8, Andy Fingerhut wrote:
>
> If you are familiar with tail recursion, then loop/recur this is Clojure's 
> way to achieve tail recursion.
>
> http://en.wikipedia.org/wiki/Tail_call
>
> The general tail call optimization mechanism as implemented in the 
> programming language Scheme, for example, means that tail-position calls 
> must not consume additional stack, and must effectively work like a goto 
> appropriate muddling of stack frames to pass the parameters to the new 
> function (which might be a recursive call, or could be to a different 
> function).  Whether the tail call is recursive or not, the return address 
> of the original calling function doesn't change after the goto.
>
> Clojure's loop/recur only implements tail recursion, not general tail-call 
> optimization.  tail recursion is far more commonly used in languages that 
> have it than the general tail-call optimization to arbitrary functions.
>
>
> Specifically on your questions about the return address, suppose function 
> foo calls function bar, and bar has the loop/recur inside of it.  At the 
> time when foo first calls bar, it saves a return address inside of foo so 
> that when bar returns, it continues in foo just after where the call to bar 
> was.
>
> loop/recur never touches that return address.   It stays there the whole 
> time.
>
> The loop is effectively a target label for a goto, and one or more 
> occurrences of recur inside of it simply rebind the loop variable values, 
> and goot the loop's target label.  Anything deeper down on the stack is not 
> changed, and there is no pushing or popping of any return addresses.  Just 
> a goto.
>
>
> Rich would have liked to implement general tail recursion in Clojure. 
>  Here are a couple of relevant excerpts from Rich Hickey's "Clojure for 
> Lispers" talk, transcript here:
>
>
> http://jafingerhut.github.com/clojure-info/clojure-for-lispers-transcript.txt
>
> Clojure does not have tail call optimization.  Not because I'm against
> it.  I'm all for it.  It's something I had to trade off in being on
> the JVM.  However, I was just at the JVM languages summit, and tail
> call optimization, every language designer who cam up there said "tail
> call optimization, tail call optimization".  And they've heard it, and
> hopefully it will come in a future VM, hopefully soon.
>
> You've seen
> languages... SISC Scheme does tail calls in the JVM, right.  It does
> it with this whole other infrastructure.  They're calling scheme is
> nothing like Java's, right?  You have to pass additional things, or
> trampoline, or whatever.  Clojure does none of that.  Clojure has
> pedal to the metal calling conventions that match Java's, so I don't
> have tail recursion, because you can't do that unless the JVM does
> that.
>
> Andy
>
>
>
> On Nov 19, 2012, at 4:38 PM, Curtis wrote:
>
> Clojure Koans - Recursion
>
> (defn recursive-reverse [coll]
>   (loop [coll coll
>          acc '() ]
>      (if (= (count coll) 0)
>         acc
>        (recur (rest coll) (cons (first coll) acc))
>      )
>   )
> )
>
> I struggled with this one for a while - I don’t want to admit it, but 
> honestly even though i have been coding since I was 16 years old - there 
> are still many areas where I am rusty or weak.
>
> There is actually a surprising amount of low level concepts operating in a 
> list recursive reverse in clojure.
>
>    - tail-call recursion
>    - accumulator
>    - loop construct
>
> I have some questions about how this “special form”  
> loop<http://clojure.org/special_forms#Special%20Forms--(loop%20%5Bbindings*%20%5D%20exprs*)>
>  operates 
> with recur<http://clojure.org/special_forms#Special%20Forms--(recur%20exprs*)>
>
> I think I need to make sure that I always remember the following :
>
>    - the arity of the recur call must match the arity of the loop form
>    - recur must be in the tail position.
>
> I’m not sure how this loop / recur mechanism is implemented in the JVM - I 
> imaging that the binding created by ‘loop’ is associated with registers 
> that are overwritten as part of the call to ‘recur’. The documentation says 
> the bindings are rebound on call of recur in parallel and the execution of 
> recur - is done in order.
>
> My questions are
>
>    - Is recur causing some kind of local jump after each binding?
>    - What happens with the return address? 
>    - If recur doesn’t consume stack - what is going on with the return 
>    address? 
>    - Is the return address always the same for the same recursive call?
>
> More importantly - Is there a chapter in Knuth AOC that could help me with 
> this? Any other resources?  
>
> I feel like I am really missing some context. Am I missing anything 
> obvious, important or insightful?
>
>

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Reply via email to