[Top][All Lists]

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

Re: eval

From: Marius Vollmer
Subject: Re: eval
Date: 05 Feb 2001 01:58:00 +0100
User-agent: Gnus/5.0803 (Gnus v5.8.3) Emacs/20.7

Dirk Herrmann <address@hidden> writes:

> On 4 Feb 2001, Marius Vollmer wrote:
> > I find this and what has been discussed in the sequel needlessly
> > complicated.  What is wrong with this:
> > 
> >     Conceptually, we should probably isolate the current-module from
> >     eval.  We should have `with-current-module' and
> >     `eval-in-current-module' [I like long names], and `eval' would be
> > 
> >         (define (eval exp env)
> >           (with-current-module env
> >             (eval-in-current-module exp)))
> OK, if I understand your idea, the functions/macros would have the
> following semantics:

No, I don't think I made myself clear enough.  What I propose is a
_very_ simple thing.

We have a fluid in the system called `the current module'.  We can
access it with the function `current-module' and set it with
`set-current-module'.  The value of this fluid is used as the
top-level environment for code evaluated by `eval-in-current-module'.
The function `eval-in-current-module' does only inspect the current
module once before starting the evaluation and does not modify it
itself in any way.

The current module does _only_ affect the behaviour of
`eval-in-current-module'.  It does not in any way affect the execution
of code already in the system (such as closures that were the result
of previous calls to `eval-in-current-module').  It is, in effect a
parameter to eval-in-current-module that is passed in a funny way, not
as a formal parameter, but as a global, `special' (in CL parlance)
variable.  We could make it a proper formal parameter, but the repl
and `load' would need the concept of a current module anyway, so we
can just as well make it concrete right now.

[ This is exactly the behaviour prior to your change that made `eval'
  save and restore the current module.  Thus, I propose to revert that
  change and rename `eval' to `eval-in-current-module'. ]

Then, we need to provide a R5RS compliant version of `eval' that does
the Right Thing in the presence of modules.  The right thing is to set
the current module to its second argument while evaluating its first
argument, but shielding the rest of the system from this temporal
change of the current module.

Facilities like the repl and `load', that explicitely want the
evaluated code to allow to change the current module, can use
`eval-in-current-module'.  They need to be careful to not mess with
the current module as observed from the outside, tho.

> * (eval-in-current-module exp) evaluates exp in whatever is the current
> module, and whichever module happens to be the current module at the end
> of the evaluation will be the current module for the environment _after_
> the evaluation.

I don't know what you mean with "the current module for the
environment".  What I'm talking about is only the value of the fluid
that implements `current-module'.  There is no interaction with the
system beyond that.

> In other words, eval-in-current-module may potentially change the
> top-level-environment for the code surrounding the call to
> eval-in-current-module.

No, only when `eval-in-current-module' is used at the top-level of
code that is fed to the repl or to `load'.  For code not at the
top-level, the corresponding module has been memoized and can't be
changed.  See below for more details.

> * (with-current-module env body) switches to the environment env and
> evaluates the body in that environment.

No, while body executes, `current-module' returns `env'.  The name
lookup for identifiers in `body' is done using the module that was
also used for looking up `with-current-module'.  (The name lookup for
identifiers in `body' would only be affected when `body' would be at
the top-level.  But with the usual implementation, by using
`dynamic-wind', it will end up in a closure anyway.)

> Nice.  However, I think that we should still be aware of the underlying
> problem:  With your approach it is possible to break the rule of
> lexical scoping:
>   (define foo 1)
>   (eval-in-current-module exp some-module)
>   (display foo)
> Here, foo is not necessarily bound to the same location as is the
> identifier foo in the first line.

[ There is no second argument to eval-in-current-module. ]

What happens depends on whether or not your code is executed at the
top-level, by typing it at a repl, for example.

When it is executed at the top-level then the second `foo' might refer
to a different binding than the one created by the first line of your
code.  This is no problem and is in fact intended, I would say.  This
is the way `define-module' works, and I think we should keep such a

[ I would probably argue that `define-module' should not set the
  current module, but that we should have a `in-module' function to do

When your code is not executed at top-level, like when calling the
following function `bar'

    (define foo 1)

    (define (bar exp)
      (eval-in-current-module exp)
      (display foo))

then the reference to `foo' inside `bar' can not be diverted to a
module different from the on that contains the definition of `bar'.
This is because the module that is used to look up the names in `bar'
is fixed when the closure for `bar' is constructed.

This use of `eval-in-current-module' should be much more common than
the top-level case.  This is how the repl is implemented, for example.

> OK, so what is the difference to my approach?  With my approach,
> eval can not be used to break lexical scoping.  (I agree, though,
> that it is somewhat clumsy to modify some glocal variable as a

What is this?  Interesting word, indeed... :-)

> sideeffect to eval.)

reply via email to

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