Update to SRFI 72 Andre van Tonder (29 Aug 2005 19:20 UTC)
Re: Update to SRFI 72 (Sorry I'm lost) Keith Wright (31 Aug 2005 04:02 UTC)
Re: Update to SRFI 72 (Sorry I'm lost) Panu Kalliokoski (31 Aug 2005 12:19 UTC)
Re: Update to SRFI 72 (Sorry I'm lost) Andre van Tonder (31 Aug 2005 15:22 UTC)

Re: Update to SRFI 72 (Sorry I'm lost) Andre van Tonder 31 Aug 2005 15:22 UTC

On Wed, 31 Aug 2005, Keith Wright wrote:

> Although the above quotation occurs three times almost verbatim,
> in the abstract, the introduction, and the specification, it does
> not get any clearer with repetition.  As Brian Smith used the term
> "reflective tower" it referred to an interpreter for a language
> that could express modifications to its own interpreter.  I don't
> think that's what you are after, is it?

> The second mention of the "infinite reflective tower" is followed
> by a reference [11] to Richard Kelsey and Jonathan Rees
> - The Scheme 48 implementation  http://s48.org/
> but a couple hours searching the Scheme 48 manual at that
> web site turned up no mention of reflective towers, and not much
> about macro expansion.

I'll try to rewrite this more clearly.  I mean a reflective tower in the Scheme
48 sense, also called a syntactic tower by the authors, who indeed criticise
the word "reflective" as a misnomer, though it seems to be widespread in the
Scheme folklore.  The Scheme 48 manual is notoriously cryptic, to the point of
unusability, but there is a mention on the page:

   http://s48.org/1.2/manual/s48manual_33.html

If someone else has a better reference to the Scheme 48 tower, I'd be grateful
for it.

> Perhaps a better reference would be
> <a href="http://www2.parc.com/csl/groups/sda/projects/reflection96/abstracts/queinnec.html">
> Queinnec - Macroexpansion Reflective Tower</a>

I'll add the reference.

> A couple of examples of odd scope rules just isn't enough for me
> to figure out the plan.  This seems to be a very big change from
> the previous proposal, and not like anything that I understand well.
>
>> * Added BEGIN-FOR-SYNTAX.

Maybe this will help:  In the example

   (define x 1)

   (begin-for-syntax (define x 2))

   (let-syntax ((m (lambda (form)
                     (quasisyntax (list x ,x)))))
     (m))  ==> (1 2)

one would get different answers depending on whether you evaluate the
sequence of expressions one by one in the REPL, or compile the whole thing and
then run it, *unless* the runtime x and the expand-time x live in separate
namespaces or, equivalently, runtime and expand-time variables have separate
lexical scopes.

It is still lexical scoping.  Any programmer worth her salt will know that the
first x in (list x ,x) denotes a runtime variable and the second x an
expand-time variable, and be able to look up the appropriate lexically preceding
binding for each.

I consider this "invariance under compilation" property the right thing to do.

> The phrase:
>> ... the hygiene algorithm of this SRFI implements a refinement of
>> lexical scoping that takes into account the level of use of an
>> identifier in determining its meaning.
>
> might be better worded as: the algorithm of this SRFI totally ignores
> lexical scoping by making the meaning of an identifier depend upon
> an invisible property called its "level" rather than its position
> in the source code. ...but I have already stated my objections
> when you first brought up this idea.

I think it is clear that one has different environment bindings at expansion
time and at runtime.  In fact, there is no reason that the expansion-time
bindings have to implement standard Scheme.  For example, the compile-time CAR
can be different from the runtim CAR.  So the compile-time language can be
different from the runtim language.

For argument's sake, let's call the runtime-language Scheme and the
compile-time language Pascal.  Now Pascal binding forms and Scheme
binding forms a priori have nothing to do with each other, so I would be very
surprised if the inner Pascal LET were to affect the x in (syntax x) at all in
the following.

   (let ((x 1))
     (let-syntax ((m (lambda (form)
                       (let ((x 2))
                         (syntax x)))))
       (m)))  ==> 1

Indeed, the x in (syntax x) represents a Scheme variable, not a Pascal variable.
It should therefore be bound by the enclosing outer Scheme LET.   In other
words, Scheme code and Pascal code should have separate lexical scopes.

>> * Added SYNTACTIC-WIND.
>
> Oy.

This allows one to do a computation before and after expanding a block of code.
It is useful for maintaining environments at expansion time when implementing
things like syntax-case and pattern matchers.  For example, in the syntax-case
macros I used it for maintaining the environment of pattern variables.

I included it because without it I do not know how to write syntax-case as a
library macro.  I do not wish to specify syntax-case as a primitive.

>> * Removed EXPAND.
>
> Why?

Because just like EVAL, EXPAND really does not make sense without a second
argument specifying the environment.  I did not wish to overcomplicate the SRFI
with a complicated explanation (and implementation) of a primitive that is used
mainly for debugging.

> ...and if it is gone, why is this code in the section
> on the reflective tower?
>
>     (for-each (lambda (form) (eval (expand form))) sequence)
>       == (for-each eval (map-in-order expand sequence))

The "schematically" was meant to indicate that it is just a pseudocode
expression of the previous verbal phrase.

> In other words, would the old srfi be compatible
> with the reflective tower, except that it would give errors
> (identifer used outside its scope of definition) in some cases
> where the tower would find and use a binding occurrence that
> would appear to be shadowed?

My view is that it is just wrong for a binding form in one phase to affect
variables in another phase at all.  I consider the out-of-scope errors in
comparable macro systems a bug.

Cheers
Andre