Hi,

to implement letrec in a language with eager evaluation strategy some
kind of mutability is probably needed. Consider for example a self-
referential definition such as

(let [fibo (lazy-cat [1 1] (map + fibo (rest fibo)))]
  (take 10 fibo))

This will not work since fibo is not in scope when the binding is
established. The standard solution would probably be something like
this

(let [fibo (promise)]
  (deliver fibo (lazy-cat [1 1] (map + @fibo (rest @fibo))))
  (take 10 @fibo))

Not as nice as the original version due to explicit dereferencing, but
workable. As an alternative one could use a macro to expand to this
and use a code walker (or symbol-macros) to automatically include the
@ calls. The following is untested, but should be close:

(defmacro letrec [binding & body]
  (let [[var expr] binding
        g-var (gensym)]
    `(let [~g-var (promise)]
       (symbol-macrolet [~var @~g-var]
          (deliver ~g-var ~expr)
          ~@body))))

and voila

(letrec [fibo (lazy-cat [1 1] (map + fibo (rest fibo)))]
  (take 10 fibo))

produces (1 1 2 3 5 8 13 21 34 55).

Best,

  Nils

-- 
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