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

next report on Scheme



	    Finally, has someone proposed already a

			    call-with-current-environment

	    similar in spirit to call-with-current-continuation?

    (1)	The environment could be a function
			    Variable --> Value
	    to model the evaluation of a variable
	    and/or
		    Bound-Variable * Value ---> Unspecified
	    to model set!

    (2)	Or it could be a function
			    Variable --> Location
	    although it would introduce the concept of location,
	    and of accessing and updating a location.
	    Similarly to define a new location, at the top level or internally.

	    Anyway it would functionalize the environments got from THE-ENVIRONMENT
	    in CScheme.

This procedure has been proposed in the past.  There are a few
problems with it, some political and some technical:

1) Not all implementations support first class environments.
Furthermore, some designers/implementors abhor them.  It is therefore
unlikely that consensus will be reached on anything involving them.

2) The semantics of a procedural CALL-WITH-CURRENT-ENVIRONMENT are not
clear.  In particular, which environment is handed to the receiver?

    Many possibilities come to mind, including the following:

    1: The environment where CALL-WITH-CURRENT-ENVIRONMENT is closed.

    2: The environment where the variable CALL-WITH-CURRENT-ENVIRONMENT is
    evaluated.

    3: The environment where the combination which results in an
    application of the value of CALL-WITH-CURRENT-ENVIRONMENT is
    evaluated.

    4: The environment where the receiver is closed.

    5: The environment where the body of the receiver will be evaluated.

None of these are really adequate:

    1: Pretty useless.  May as well define it as a constant.

    2: It makes some variables special, hard to handle by
    compiler/interpreter.  Furthermore, it probably does not have the
    desired effect in cases like

    (define (foo) call-with-current-environment)

    (let ((x 3))
      ((foo) (lambda (env) env)))

    3: This is probably the desired semantics.  It has the nice
    property that THE-ENVIRONMENT can expand trivially into

    ((absolute call-with-current-environment) (lambda (env) env))

    Unfortunately, it forbids certain kinds of EVLIST tail recursion.

    4: This is pretty good.  The same expansion that works in 3 above
    works here too.  Unfortunately it forbids certain kinds of
    environment optimization.  For example in,

    (call-with-current-environment (generate-proc 2 3))

    GENERATE-PROC must return a procedure whose format can be
    understood by CALL-WITH-CURRENT-ENVIRONMENT.  Since GENERATE-PROC
    might be compiled out of line, this forces the compiler to avoid
    environment optimization in most environments.

    5: This has the same problems that 4 does and it harms incremental
    definition as well:  The environment obtained is most likely not
    the one where the definitions are desired (the parent environment
    frame is the one the user probably wants).

The real issue is that by being a special form, the correct things
"happen":

The environment where the special form is evaluated is the environment
desired, so it is certainly available when the code is executed.

A convenient syntactic marker is provided so that optimizing compilers
can discriminate at compile time between environments used in a
"first-class" way, and those which cannot be examined by the user in a
similar way (modulo debuggers, etc, which are always special).  The
compiler has full freedom to implement these other environments, since
only code generated by the compiler at that time (or the debugger)
will ever need to examine them.

In order to understand my point, please consider the following
(somewhat forced) analogy:

Eliminate LAMBDA as a special form from the language in favor of a
procedural constructor:

(lambda (x y z) <code>)

becomes

(make-procedure '(x y z) '<code>)

The "bad" cases arise from things similar to

(foo '<code>)

where FOO is compiled in a separate file and is defined as

(define (foo code)
  (make-procedure '(a b c) code))

or

(make-procedure (generate-arg-list) '<some code>)