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

Proposal for EVAL



*      The proposal:

*      (EVAL <expression> <environment specifier>)		essential procedure

*      EVAL evaluates the expression in the environment indicated by
*      environment specifier.  Environment specifier may be the return value
*      of one of the procedures NULL-ENVIRONMENT, INTERACTION-ENVIRONMENT,
*      SCHEME-REPORT-ENVIRONMENT, or implementation-specific extensions.  No
*      other operations on environment specifiers are defined by this
*      proposal.

*      Implementations may allow non-expression programs (i.e. definitions)
*      as the first argument to EVAL _only_ when the second argument is the
*      return value of INTERACTION-ENVIRONMENT or some implementation
*      extension.  In other words, EVAL will never create new bindings in the
*      return value of NULL-ENVIRONMENT or SCHEME-REPORT-ENVIRONMENT.

*   This constraint is so stringent that one of the most important
*   uses of EVAL, namely implementing R4RS macros, will only be possible
*   with first-class environments!

Not true.  INTERACTION-ENVIRONMENT can be trivially supported by
dialects such as MacScheme and Indiana's Scheme 84 without any support
for what is usually called first-class environments.

In fact

(define (interaction-environment)
  '*THE-INTERACTION-ENVIRONMENT*)

(define (eval expr env)
  (case env
    ((*THE-INTERACTION-ENVIRONMENT*)
     (let ((fname (make-temporary-filename)))
       (with-output-to-file fname (lambda () (write expr)))
       (load fname)))
    ...))

is a possible (although silly) implementation that uses LOAD, which is
in the current report (I thought it had been flushed) and causes no
problems for anyone who already supports LOAD.


*   The first problem here is the decision that macros share the same
*   "binding space" with regular programs.  This gives Scheme a self
*   referential ability that neccessitates use of INTERACTION-ENVIRONMENT.

Only if you can introduce macros dynamically.  If you can, then you
already have to have an evaluator that can handle this situation, and
EVAL just gives you programmatic access to it.

*    Note: It is actually this property that causes my dislike of EVAL.  I
*    have no problem with an EVAL which can not modify the environment of
*    the executing program.

That is precisely the point of NULL-ENVIRONMENT and
SCHEME-REPORT-ENVIRONMENT, which are essential while
INTERACTION-ENVIRONMENT is not.

*   The second problem is that macro implementations define new symbols
*   using EVAL (correct me if I am wrong on this).  This again requires
*   use of INTERACTION-ENVIRONMENT and hence first-class environments.

Again, you are making an invalid inference.  INTERACTION-ENVIRONMENT
in no way demands or expects first-class environments.

*   Although it is neat that EVAL can be purely functional, I don't
*   understand the neccessity for excluding new definitions from the
*   NULL-ENVIRONMENT and SCHEME-REPORT-ENVIRONMENT.  As a "no eval"
*   implementor I would only be supporting NULL-ENVIRONMENT and
*   SCHEME-REPORT-ENVIRONMENT with an interpreter.  It is not a problem
*   for me to have the interpreter be able to extend an environment.

The problem has to do with requiring only a finite number of
environment specifiers, and with consitency.

After all, if you modify the environment specified by the return value
of a single call to NULL-ENVIRONMENT, then the next time you call it,
either you have to return a different specifier (so that the
environment will be as expected) or the environment is no longer
"null".  The first option is objectionable because it would result in
the implicit requirement for arbitrarily many null environments, and
once you can support that, then you do have first-class environments,
which I do not want to require.  The second is objectionable because
it has bad effects for modularity (particularly with respect to
SCHEME-REPORT-ENVIRONMENT).


*      (INTERACTION-ENVIRONMENT)				procedure

*      This procedure returns a specifier for an environment that contains
*      implementation-defined bindings, typically a superset of those listed
*      in the report.  The intent is that this procedure will return a
*      specifier for the environment in which the implementation would
*      evaluate expressions dynamically typed by the user.

*   Since not all implementations are interactive, I don't think this is
*   the proper criterion for describing this environment.  How about the
*   environment into which scheme code is LOADed.  This brings up another
*   point.  LOAD is intimately connected to EVAL.  I think you may need to
*   refine the definition of LOAD as well.

You are right.  I had forgotten that LOAD had remained in the report.
On the other hand, any implementation that supports LOAD is implicitly
interactive, since the combination of READ, WRITE, and LOAD gives you
a rudimentary REPL.

If you have a better suggestion for wording or even for the name of
the procedure, I'll be happy to consider it.  I don't consider myself
either a good wordsmith or a good writer, so I will be happy to defer
to others.


*		      RATIONALE:

*      Many implementations will specify the meaning for single-argument EVAL
*      to be the same as for EVAL with two arguments when the second argument
*      is the result of (INTERACTION-ENVIRONMENT).

*   Perhaps this, at least, can become an optional procedure in R5RS.  If
*   two argument eval people object to using EVAL for this purpose, how
*   about EVAL1.

I don't object to specifying one argument EVAL as optional with the
understanding that it is equivalent to

  (EVAL <expr> (INTERACTION-ENVIRONMENT))


*      "Pascal-like" implementations can support both NULL-ENVIRONMENT and
*      SCHEME-REPORT-ENVIRONMENT since the environments denoted by the return
*      values of this procedure need not share any bindings with the current
*      program.  A version of EVAL that supports these but not
*      INTERACTION-ENVIRONMENT can be written portably, but can be better
*      written by the implementor, since it can share code with the default
*      evaluator/compiler.

*   SCM still couldn't use its builtin interpreter.  Code gets modified as
*   it is executed to memoize variable locations.  If the same code were
*   to be EVALed in two different environments (eg., the 2 mentioned
*   above), the second EVAL could be referencing non-existent locations.

It can be done.  The MIT Scheme system does this (for compiled code
that heavily uses first-class environments) by essentially doing a
code (graph) copy before going into the evaluator proper.  There is no
requirement that the code being executed is EQ? to the argument to
EVAL.  In other words, it is perfectly legal to do the following

(define (EVAL expr env-spec)
  (execute (compile expr env-spec)))

where compile rewrites your code into a different structure.

*      The concerns of the various positions:

*      "No eval": Supporting EVAL with NULL-ENVIRONMENT and
*      SCHEME-REPORT-ENVIRONMENT is harmless since they are implementable in
*      user code.  They are convenient as a hook for implementations that
*      provide more features and as a way for the implementation to insert a
*      compiler (which a portable version could not expect/use).

*   Yes, but a primary use of EVAL in implementing R4RS macros is not
*   supported as I said previously.

It is, by the use of INTERACTION-ENVIRONMENT in exactly those
implementations on which the issue arises.