[plt-scheme] Android; compiling to Java byte code; Clojure

From: Benjamin L. Russell (dekudekuplex at yahoo.com)
Date: Thu Nov 22 01:01:19 EST 2007

According to the Clojure Web site, "There is no
tail-call optimization, use recur."  ( See
http://clojure.sourceforge.net/reference/lisps.html .)

Here is what their site says about recur ( see
http://clojure.sourceforge.net/reference/special_forms.html
):

> (recur exprs*)
> 
> Evaluates the exprs in order, then, in parallel, 
> rebinds the bindings of the recursion point to the 
> values of the exprs. If the recursion point was a fn

> method, then it rebinds the params. If the recursion

> point was a loop, then it rebinds the loop bindings.

> Execution then jumps back to the recursion point.
The 
> recur expression must match the arity of the 
> recursion point exactly. In particular, if the 
> recursion point was the top of a variadic fn method,

> there is no gathering of rest args - a single seq
(or 
> null) should be passed. recur in other than a tail 
> position is an error.
> 
> 
> Note that recur is the only non-stack-consuming 
> looping construct in Clojure. There is no tail-call 
> optimization and the use of self-calls for looping
of 
> unknown bounds is discouraged. recur is functional 
> and its use in tail-position is verified by the 
> compiler.
> 
> (def factorial
>   (fn [n]
>     (loop [cnt n acc 1]
>        (if (zero? cnt)
>             acc
>           (recur (dec cnt) (* acc cnt))))))

The special form loop binds cnt to n and acc to 1. 
Notice the lack of explicit recursion in the above
procedure, and the loop special form.  

For reference, here's their description of the let
special form:

> (loop [bindings* ] exprs*)
> 
> Loop is exactly like let, except that it establishes

> a recursion point at the top of the loop, with arity

> equal to the number of bindings. See recur.

Compare their above procedure with the tail-recursive
version of the same function in SICP ( see
http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-11.html#%_sec_1.2.1
):

> (define (factorial n)
>   (fact-iter 1 1 n))
> 
> (define (fact-iter product counter max-count)
>   (if (> counter max-count)
>       product
>       (fact-iter (* counter product)
>                  (+ counter 1)
>                  max-count)))

It seems to me that recur and loop together allow a
more intuitive version of the equivalent of tail
recursion in this case than the regular tail recursion
in the equivalent SICP Scheme version.

Any opinions?

Benjamin L. Russell

--- "Geoffrey S. Knauth" <geoff at knauth.org> wrote:

> During the discussion of Google's Android Open
> Handset Alliance  
> Project, Noel Welsh commented, "the route to getting
> Scheme code onto  
> Android is to compile to Java bytecode."
> 
> Begin forwarded message:
> 
> > From: Heow Eide-Goodman <lists at alphageeksinc.com>
> > Date: November 21, 2007 16:46:57 EST
> > To: "lisp at lispnyc.org" <lisp at lispnyc.org>
> > Subject: [Lisp] Clojure Resources
> 
> If you missed the Clojure presentation, you missed a
> treat.
> 
> Rich Hickey presented the culmination of many years
> of work into his new
> dynamic lisp-like language.
> 
> Not only does it support a REPL, but everything is
> dynamicly compiled
> into Java byte-code on the fly. There really is no
> interpreter!
> 
> Besides performance, Clojure supports run-time
> polymorphism and an
> impressive take on making concurrent programming
> easy by the use of
> software transactional memory.
> 
> Slides and audio coverage are available here:
> 
>   http://lispnyc.org/wiki.clp?page=past-meetings
> 
> _________________________________________________
>   For list-related administrative tasks:
>  
> http://list.cs.brown.edu/mailman/listinfo/plt-scheme
> 



Posted on the users mailing list.