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
