The original 1975 memo on Scheme described evaluate, which was analogous to Lisp's traditional eval function. evaluate took a single argument, an S-expression, and invoked an interpreter on it. For example: =0pt=0pt=0pt =0pt[] (let ((name '+)) (evaluate (list name 2 3))) 5
Scheme being lexically scoped, however, there was some confusion over which environment the expression was to be evaluated in. Should =0pt=0pt=0pt =0pt[] (let ((name '+)) (let ((+ *)) (evaluate (list name 2 3))))
evaluate to 5 or to 6?
To clarify matters, the Revised Report replaced evaluate with enclose, which took two arguments, a lambda-expression and a representation of an environment from which to supply bindings of the lambda-expression's free variables. For example: =0pt=0pt=0pt =0pt[] (let ((name '+)) (let ((+ *)) ((enclose (list 'lambda '() (list name 2 3)) (list (cons '+ +)))))) 6
This forced the programmer to be explicit about the lambda-expression's enclosing environment.
For various technical and practical reasons, there was no eval analogue in subsequent Scheme reports. The major stumbling blocks were how to describe eval formally and how to define something that makes sense in all extant variants of the language. Some Scheme implementations contain a distinguished top-level environment, while others extend the language by providing ways to create multiple environments, any of which might serve equally well.
The eval proposal adopted at the June meeting, which I reproduce here, is one that comes from Bill Rozas.
(eval expression environment-specifier) essential procedure
eval evaluates expression in the environment indicated by environment-specifier. environment-specifier may be the return value of one of the three procedures described below, 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.
(scheme-report-environment version) essential procedure
Version must be an exact non-negative integer corresponding to a version of one of the Revised Reports on Scheme. This procedure returns a specifier for an environment that contains exactly the set of bindings specified in the corresponding report that the implementation supports. Not all versions may be available in all implementations at all times. However, an implementation that conforms to version n of the Revised Reports on Scheme must accept version n. If scheme-report-environment is available, but the specified version is not, the procedure will signal an error.
The effect of assigning (through the use of eval) a variable bound in a scheme-report-environment (e.g. car) is unspecified. Thus the environments specified by the return values of scheme-report-environment may be immutable.
(null-environment) essential procedure
This procedure returns a specifier for an environment that contains no variable bindings, but contains (syntactic) bindings for all the syntactic keywords defined in the report, and no others.
(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.
Rozas explains: ``The proposal does not imply the existence or support of first-class environments, although it is compatible with them. The proposal only requires a way of associating tags with a finite set of distinguished environments which the implementations can maintain implicitly (without reification).
```Pascal-like' implementations can support both null-environment and scheme-report-environment since the environments specified by the return values of these procedures 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 or compiler.''
Here ``Pascal-like'' refers to implementations that are restricted to static compilation and linking. Because an eval that doesn't support
interaction-environment can be written entirely in the Scheme language described by the rest of the report, it raises no troublesome questions about its formal semantics.