On 9/6/07, <b class="gmail_sendername">AndrevanTonder</b> <<a href="mailto:andre@het.brown.edu" target="_blank" onclick="return top.js.OpenExtLink(window,event,this)">andre@het.brown.edu</a>> wrote:<div><span class="gmail_quote">


</span><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
On Tue, 4 Sep 2007, Lynn Winebarger wrote:</blockquote><div><br>    Thanks for your thoughtful response, Andre.  I will present an alternative viewpoint, which I hope will help delineate the subset of programs that should be defined by ERR5RS.  Otherwise I would just be venting my spleen without making a positive contribution.
<br>    I disagree with most of your assertions below to the extent they are unqualified as being for consistency with R6RS.  Consistency with R6RS (short of bug-for-bug compatibility, to use Will's words) is a reasonable goal without having to make overly broad claims.  First, I need to make a digression
<br><br></div>    After some contemplation, I think a significant problem is the nature of "define".  To my knowledge, it is the only construct in R5RS which falsifies the "a very small number of rules for forming expressions, with no restrictions on how they are composed" statement.  In particular, you can't place defines arbitrarily in a body.  What's more, the chosen semantics for internal defines are inconsistent with those of top-level defines.  I suppose the intent was to remove some layers of nesting, but the effect in R6RS has been taken to the extreme - top-level defines have been redefined to be consistent with internal defines!
<br>     For example, let's take<br>(define bar 1)<br>(define foo<br>   (lamdba (x)<br>      (if x<br>          (define bar 100)<br>          (set! bar (+ bar 1)))<br>      #t)))<br><br>There is one sensible, consistent way to interpret this code, which is that the (define bar 100) establishes a global binding of bar, not a local one.   The requirement derives from lexical scoping.   This is illustrating by the following sequence of expressions (hopefully it is obvious why this sequence represents the undesirable alternative):
<br>(foo #f)<br>
(display bar) => 2<br>
(foo #t)<br>
(display bar) => 100<br>
(foo #f)<br>
(display bar) => 101<br>
<br>What does this have to do with "shared" versus "separate" bindings?  Only that the internal-define requirements are all about separating phases, where the top-level definitions (in the presence of syntax-case, anyway) are effectively evaluated in phases above the expansion of all subsequent expressions, with bindings shared in downward phases.   You can write programs that obey the internal-define requirements with top-level semantics, but not vice-versa.  Therefore the top-level notion of define (and hence the implied phasing and down-phase sharing of bindings) is more desirable for a power-hungry programmer.  
<br>    Alas, I do not harbor any hope that the meaning of the define keyword will be made consistent in any foreseeable version of Scheme.<br><br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">

> There were a lot of messages in that thread.  In the first message,<br>> Andre prefered a single set of bindings for all phases, but then<br>> changed his mind a few messages later.
<br><br>I think it is clear that if one insists on a single set of bindings<br>for expand-time and runtime, one would have to recompile a program<br>before running it every time one restarts a session, or otherwise<br>include the compile-time image in the compiled object file.  I think
<br>that would be an undesirable constraint to impose on compiler-based<br>Scheme systems.<br></blockquote><div>      Only the reachable compile-time bindings.  Whether it is desirable depends on the user of the language, not the compiler writer.
<br>      This also suffers from the internal-vs-top-level define problem - a programmer can write programs that do not need to share variables between phases in implementations that do not require it, but not vice-versa.   Note that I am not suggesting run-time should be able to modify compile time values, just refer to them.  It seems to me the environment of the higher phase could be regarded as a module implicitly exporting its bindings to the run-time, with the corresponding restriction on mutation.
<br><br></div><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">(For simplicity and performance, my implementation does share a single<br>memory location for the bindings of the same identifier in phases
<br>higher than "expand", but it syntactically prohibits access to<br>bindings, even though they may be present in memory, that<br>are used outside their declared levels.  So to an extent enforcing<br>levels syntactically is orthogonal to whether the actual objects
<br>are shared or not.  Communication between levels is possible using<br>mutation of shared objects, but this is not portable and should not<br>be used.  The only way in which information can reliably be<br>communicated between levels is through syntax objects and datum->syntax
<br>on objects that have an external representation, as described in the<br>thread you mentioned).</blockquote><div><br>    Yes, I saw Matthew Flatt denigrating 3D macros.  For my taste, implementations should be required to accept arbitrary data in syntax object, in the same spirit that other values are self-quoting [yes, I am conflating constants with values].  It's not clear why limiting the programmer to expressions that have an external syntactic representations is a good idea.  On the one hand, you see what the compiler writer wishes to provide, and on the other what the program author wishes to write.  If an expression appears meaningful, it should be meaningful.
<br> </div><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">I agree with the premise of R6RS that portable programs be<br>written to not depend on the unspecified details of the instantiation
<br>semantics.  This could be seen as analogous to the constraint that<br>portable programs must not depend on the unspecified evaluation order<br>of function calls.</blockquote><div><br>    But this is an incorrect statement.  A program whose intended meaning depends upon the order of evaluation is not portable, but I can certainly write programs whose output/state varies with the order of evaluation, yet does not depend on that order for correctness.
In the same way, I might have a use for knowing the order of instantiation of libraries without requiring any particular order for correct functioning.<br><br></div><br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">

> I know I have found an analogous feature of PLT's<br>> syntax-case incredibly annoying (not being able to directly use
<br>> variable definitions inside a syntax-case body).<br><br>I know it is annoying, but it is also correct.  It avoids the even<br>more annoying phenomenon of code that works in the REPL<br>suddenly stopping working when you compile the same code (at compilation
<br>time the runtime variable does not have value, so the reference to it<br>from syntax-case will fail).  A good reference on this kind of thing<br>can be found in Matthew Flatt's paper whose title ends with<br>"you want it when", which I would recommend if you have not already
<br>read it.</blockquote><div>    <br>     If you mean "correct" in any sense other than "portable R6RS", you are not making an defensible claim.  What is annoying is that the compiler doesn't make the code work like it did at the REPL, not that the REPL does the right thing.
<br> </div>

<br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">>     If this is correct, could you (Andre, Will, or both) provide a<br>> single coherent explanation of why the separated binding are the
<br>> better semantics?  In any case, as a user I would prefer to know that<br>> it was going to be one or the other for certain.<br><br>As Will said, programs should not depend on unspecified aspects of the<br>semantics.  Maybe a good question for err5rs is whether this
<br>semantics-independence should be enforced by the implementation<br>(e.g., providing only syntax-rules) or whether one should come<br>up with a simple set of programmer's responsibilities that would,<br>if followed, ensure such independence.
</blockquote><div><br>       I don't think it should be enforced by the semantics.   That is part of the problem with R6RS.  The reason for ERR5RS to adopt a strict subset of the R6RS library syntax and semantics is that no consensus appears reachable on what the semantics of the unrestricted subset should be.  It is a shame R6RS will not explicitly state what programs will have a definite meaning, and explicitly leave the rest undefined.  The more programs you given definitions, the fewer implementations will support ERR5RS.
<br>      At least, this is how I understand this aspect of the project, and believe this email demonstrates why the reason is sound.  I have also come to understand the lament of some rrrs mailing list poster that an implementor's workshop might encourage implementors to (heaven forfend) be involved in defining the language they are implementing. 
<br><br></div>Lynn<br>PS.  Separated bindings are really a kind of dynamic scoping.  The following illustrates what I think lexical scoping would require (visibility of bindings in downward phases):<br>(define bar 10)<br>

(define-syntax foo<br>  (lambda (x)<br>     (define bar 'a)<br>     (syntax-case x ()<br>       ((_) #'bar)<br>       ((_ y) #'(set! bar y)))))))<br>bar => 10<br>(foo) => a<br>(foo 'b) => <br>bar => 10
<br>(foo) => b<br><br></div>