[plt-scheme] How is letrec different from letrec* in its use?

From: hendrik at topoi.pooq.com (hendrik at topoi.pooq.com)
Date: Sat Feb 14 07:47:11 EST 2009

On Fri, Feb 13, 2009 at 11:01:14PM -0600, Grant Rettke wrote:
> On Fri, Feb 13, 2009 at 6:35 AM, James Coglan <jcoglan at googlemail.com> wrote:
> >> I just read the spec for both letrec and letrec* and I see that the
> >> former is not evaluted in any other but the latter is evaluted from
> >> left to right. I am not getting the difference in their use. May
> >> someone please provide an illuminating example?
> 
> > (letrec) is like (let), but the evaluations take place *inside* the lambda,
> > changing their scope. The evaluations are not supposed to depend on each
> > other so evaluation order is not important (like for (let)).
> >
> > (letrec ([x 1]
> >          [y 2])
> >   (+ x y))
> >
> > is equivalent to:
> >
> > ((lambda ()
> >   (define x 1)
> >   (define y 2)
> >   (+ x y)))
> 
> This is how I interpreted its behavior from the spec:
> 
> (define-syntax my-letrec
>   (syntax-rules ()
>     ((_ ((var init) ...) body)
>      (let ((var #f) ...)
>        (set! var init) ...
>        body))))
> 
> (my-letrec
>  ((a (lambda (n) (when (< n 5) (b (add1 n)))))
>   (b (lambda (n) (when (< n 5) (a (add1 n))))))
>  (a 0))
> 
> #;(let ((a #f)
>         (b #f))
>     (set! a (lambda (n) (when (< n 5) (b (add1 n)))))
>     (set! b (lambda (n) (when (< n 5) (a (add1 n)))))
>     (a 0))
> 
> Are we saying the same thing? Is this right?
> 
> > Finally, (letrec*) is like (let*) but it uses (letrec).
> >
> > (letrec* ([x 1]
> >           [y 2])
> >   (+ x y))
> >
> > is equivalent to:
> >
> > (letrec ([x 1])
> >   (letrec ([y 2])
> >     (+ x y)))
> 
> I see. This allow for mutually recursive definitions; but as Sam said
> you can predict about behavior in situations when you are not *only*
> binding lambda expressions.
> 
> I am wondering why would people use letrec for anything other than
> binding lambda expressions if it is impossible to reason about its
> behavior? Or rather, why would it allow anything other than lambda
> expressions to be bound if you can't predict the behavior?

Might there be constructions like

(letrec ([f (cons (lambda() foo) (lambda() bar))]
         [foo (lambda() ...f...)]
         [bar ...]
        )
)

-- hendrik


Posted on the users mailing list.