chicken-users
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Chicken-users] eval environment


From: Alejandro Forero Cuervo
Subject: Re: [Chicken-users] eval environment
Date: Tue, 30 May 2006 22:32:48 -0500
User-agent: Mutt/1.5.9i

> > (define jim
>     (lambda (fun)
>         (letrec ((self (lambda (a) (+ 1 a))))
>             (fun 5))))
> > (jim (lambda (b) b))
> 5
> > (jim (lambda (b) (self b)))
> Error: unbound variable: self

This happens because only the expression inside the letrec has access
to the variables it defines.  Since your call to self does not appear
inside the letrec expression (nevermind the fact that when evaluating
your program your “(self b)” expression gets evaluated as a result of
the code inside the letrec).  This is what the experts call “having a
lexical scope” (rather than dynamical scope).  I'm told original Lisp
dialects had a dynamical scope, which made the code very difficult to
follow.  Before I came across Lisp, I had designed a similar language
with dynamical scope and programs expressed on it had a propension to
get incredibly messy.  But I digress.

You probably want to do this:

  (define jim
    (lambda (fun)
      (letrec ((self (lambda (a) (+ 1 a))))
        (fun 5 self))))

  (jim (lambda (b f) b))

  (jim (lambda (b f) (f b)))

Of course, your definition can be written with a more idiomatic form:

  (define (jim fun)
    (fun 5 (lambda (a) (+ 1 a))))

> I was hoping that when "fun" is run and it didn't find "self" in its
> own little environment, then it would look for it in the next
> envornment, which would be within the letrec.  Do I have to run eval
> on '(fun 5) with the current environment somehow?

Think of each environment as a list of symbols, with no such thing as
"the next environment".  Let (or letrec) copies the entire enviroment
it appears in, defines its variables in the resulting environment and
uses it to evaluate its inner forms.  When a procedure defined with a
lambda form gets called, the environment used to evaluate its body is
the one that was in use when it was created (with the addition of the
parameters bound to the values passed in the call) instead of the one
in use when it was called.  Again, there's no such thing as "the next
environment".

Scheme implementations are actually smarter than what I described and
optimize the whole process.  Internally, environments usually do have
a "next environment".  The whole result, however, is exactly the same
as what I described above, only faster.

I hope my explanation made sense.

Happy Schemeing! :-)

Alejo.
http://azul.freaks-unidos.net/




reply via email to

[Prev in Thread] Current Thread [Next in Thread]