guile-devel
[Top][All Lists]
Advanced

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

Re: eval


From: Neil Jerram
Subject: Re: eval
Date: 02 Feb 2001 12:24:36 +0000

>>>>> "Dirk" == Dirk Herrmann <address@hidden> writes:

    Dirk> On 1 Feb 2001, Neil Jerram wrote:
    >>  In order that I can be sure that I understand the problem,
    >> please could you remind me about the situations in which we
    >> want evaluation of `(define-module (foo))' _not_ to change
    >> (current-environment) after the evaluation.

    Dirk> We don't want that calls to scm_eval or 'eval change
    Dirk> (current-environment), but that evaluations of code within a
    Dirk> file change the current environment for the rest of the
    Dirk> file, but not beyond that.

Thanks for clarifying.  IMO, the natural way to achieve this is

- implement define-module so that it always changes
  (current-environment)

- implement file loading so that it saves (current-environment) before
  evaluating the contents of the file, and restores it afterwards

- implement eval such that it does _not_ save and restore
  (current-environment) - i.e. eval does nothing special.

Am I missing something?  [yes - see further below!]

    Dirk>   (let* ((m (current-module))
                   (x (eval '(define-module (foo)) <some env>)))
              <further code>)

This is a strange example, but I think it would be quite reasonable
for define-module here to change (current-environment) persistently.

    Dirk>   (define-module (foo))
            (eval '(+ 1 2) (resolve-module (bar)))
            (display (current-module))

    Dirk> We would clearly say that the display command should display
    Dirk> module (foo), not module (bar).  However, the expression (+
    Dirk> 1 2) should be executed in an environment, where (bar) is
    Dirk> the current module.  Thus, eval can not be implemented to
    Dirk> take over the current module to the outer code.

Completely agree, and I think this is all consistent with my
suggestion above.  The only detail - which is probably already obvious
to you - is that resolve-module must resolve a module name and return
a module object without changing (current-environment).


<time passes...>


OK, so I was just about to send this, but I think I now understand the
difficulty.  eval _must_ restore (current-environment) to _something_
after it has finished evaluating, because it began by changing
(current-environment) to its second argument.  So the questions are:
(i) what should eval restore (current-environment) to?  (ii) if eval
is going to put some stored value back into (current-environment), how
can we make define-module work?

How about:

- two distinct fluids for (current-module) and (current-environment):
  (current-environment) is what the evaluator cares about,
  (current-module) is a higher-level concept used to make the module
  system work

- when eval starts, it sets (current-environment) to its second
  argument

- when eval finishes, it sets (current-environment) to the environment
  of (current-module)

- implement define-module so that it changes (current-module)

- implement file loading so that it saves and restores
  (current-module)

- whenever (current-module) is set, Guile changes
  (current-environment) to (current-module)'s environment.


Comparing with your SOLUTION, I think this is the same but with
  - current-module       instead of  the-interaction-module
  - current-environment  instead of  the-module
  - specification of what the-module is restored to by eval
  - specification which variable is important to the evaluator.

Regarding your GENERALIZATION,
  - I think eval will be broken if it relies on its calling code to
    restore a sensible environment; e.g.:

    (begin
      (eval '(lambda (x) x) (null-environment 5))
      (list "done"))
    =>
    Unbound variable: list

  - the value of (current-module) after evaluating file contents but
    before restoring the initial value of (current-module) could be
    returned as the result of load:

    (define (load file-name)
      (let ((outer-module (current-module))
            inner-module)
        (load-internal file-name)
        (set! inner-module (current-module))
        (set! (current-module) outer-module)
        inner-module))

    (No wind protection, and funny syntax, but you get the idea.)

  - therefore I don't think that the-module* is a useful
    generalization, and I also find the suggested connection with
    interaction-environment confusing.

I hope all this rambling helps!

    Dirk> Best regards, Dirk Herrmann

Regards,
        Neil



reply via email to

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