There seems to be no one here arguing a different point, so I'll let me  
thoughts on this be known, though I am sure some people in the community  
will vehemently disagree with me.

On Tue, 08 Sep 2009 11:40:10 -0400, Andre van Tonder <[email protected]>  
wrote:

> On Tue, 8 Sep 2009, John Cowan wrote:
>
>> Andre van Tonder scripsit:
>>
>>> In any case, macro forward-reference is probably the first thing that  
>>> will
>>> have to go if small Scheme is to be REPL-compatible.
>>
>> Indeed, and this is what worries me about the compatibility between
>> Thing One and Thing Two.  If Thing One is to have R5RS semantics in
>> both its REPL and its libraries, and Thing Two is to have the R6RS
>> semantics of top-level programs and libraries, then Thing One libraries
>> will be neither upward nor downward compatible with Thing Two libraries.
>
> No, if there is to be a Thing Two, they will have to be compatible.  It
> really is a small change (simply disallow forward uses of macros) that
> significantly simplifies the expansion process (from 2-pass to 1-pass)
> by disallowing a corner case that is hardly ever even used by anybody.
>
> One pass is simpler for users to understand.  Insisting on two-pass  
> expansion
> in R6 is very much like insisting on two-pass for evaluation, e.g.,
> insisting that
>
>    (display x)
>    (define x 1)
>
> should work just because the display is in the region of visibility of
> the binding.  No Schemer today has this expectation for definitions.
> Neither should they for syntax definitions.  The fact that you
> can make more things work with more passes does not mean it should be
> done.

Andre and John, both of you seem to think that a language, in order to be  
REPL-compatible, must maintain REPL-like semantics throughout all uses. I  
disagree with this. The REPL is first and foremost a programming  
convenience for interactive development. It is not meant to be an end user  
interface, and it is not meant to be some "primary means" of deploying  
software programs, at least not in most cases. Usually, software is  
deployed in files, and not typed in manually or loaded through the REPL.

R6RS defines the body expansion process in Chapter 10 of the main  
document. It also states that internal definitions follow LETREC*  
semantics.

Andre, you seem to think that it doesn't make sense to treat macros and  
procedures as consisting of two passes. However, this really *is* how  
things happen, and is consistent throughout the community. Code is  
expanded, and then evaluated. In the case of the REPL, this happens on a  
per form, one at a time level. In other contexts, this also usually  
happens at a per form level, but there is often a single module form  
encapsulating the syntax, and the whole code can thus be expanded in a  
single pass.

The expansion process laid out in chapter 10 can be paraphrased simply in  
relation to definitions using 'define' and 'define-syntax' easily: do the  
syntax first, then do the rest. In fact, this is a very natural way to  
think about things, because we do have two phases going on. Macro forward  
references, when thought of in these terms, do not seem to funny. They  
just happen out of course. You delay evaluating definitions until you have  
all the definitions and syntax ready within that current scope.

That last part is important. Within that current scope allows us to create  
two reasonable interpretations of the semantics, one which applies aptly  
to the REPL and the other which makes more sense for normal code.

In normal, packaged code, I want all of my definitions to exist in the  
same scope, and I don't like the idea of implying a constant interleaving  
of syntax expansion and code evaluation. I want all the syntax definitions  
to occur first along with expansion, and then the definitions can come  
after that. This is more or less what happens. [I am being intentionally  
fuzzy here.]

Now, the REPL is a different beast. In fact, we will not ever be able to  
have consistent semantics between libraries, top level programs (which  
should be implicitly wrapped in a library form), and the REPL. You can't  
get perfect semantics, and I argue (against some of the other members of  
the community) that we don't have to try overly hard to bring the two  
together. They exist for different reasons, so let's allow for some  
differences in semantics.

In other words, I want my REPL to be useful as a general interactive  
experimentation device, I don't need it to behave exactly like a normal  
program would, and in fact, I don't *want* it to do so, because some  
things which are convenient when dealing with whole chunks of code don't  
make sense when I just want to type forms in one by one.

In the REPL, we can have things expanded and evaluated in two separate  
phases, same as always, but it can occur on a form by form level, so of  
course, I wouldn't expect one form to expand correctly if it uses a macro  
that I haven't defined yet in the REPL. However, I don't expect that  
behavior when I wrap everything in a LET form, say. In that case, since  
the syntax is defined at the "time" as I use it to define some run-time  
name, I want it to be visible.

I hope I have made myself clear here, but to me, the solution to these  
issues is to just disregard them as real problems. Let a REPL semantics be  
developed that naturally extends the normal semantics to this interactive  
form, and you don't need more. They don't have to be the same. No need to  
make them needlessly different, but there is little reason -- and that  
unconvincing to me -- to force them to come together.

-- 
Of all tyrannies, a tyranny sincerely exercised for the good of its  
victims may be the most oppressive. -- C. S. Lewis

_______________________________________________
r6rs-discuss mailing list
[email protected]
http://lists.r6rs.org/cgi-bin/mailman/listinfo/r6rs-discuss

Reply via email to