On Sep 14, 2009, at 2:31 PM, Andre van Tonder wrote:

> On Mon, 14 Sep 2009, Shiro Kawai wrote:
>
>> I've seen users confused by toplevel forms behaving
>> differently when wrapped by begin.  I like to follow a
>> better REPL semantics if one is ever agreed.
>
> I agree, having the semantics change when wrapped by BEGIN
> is just crazy.  IMO it should be a fundamental property
> of BEGIN that flattening BEGINs do not change the meaning.

The consequence of this property when applied to the REPL is that the  
R6RS two-pass semantics are fundamentally incompatible with the idea  
of a REPL.

I think we can outline three properties of which you can choose two in  
any given implementation:

1. Inner `define-syntax' forms should be allowed, and should follow  
the two-pass semantics given by the R6RS.
2. Inner definitions and top-level `begin' forms should behave  
consistently.
3. `begin' at the REPL should behave as if the body forms were entered  
individually at the REPL.

The R6RS chose properties 1 and 2 for library bodies. Top-level R6RS  
programs allow expressions and definitions to be mixed in a top-level  
begin, but this was not extended to library bodies or inner definition  
contexts.

My suggestion is that property #3 should be sacrificed, following the  
lead of the R6RS implementations that provide a REPL. `begin' is a  
binding form. We can specify the behavior of `begin' within inner  
definitions or when nested in a `begin' as being equivalent to  
splicing without applying this to the interactive top-level, where  
certain types of mutually recursive definitions are by nature  
impossible.

It is also plausible to weaken #1 to allow Chicken-style inner `define- 
syntax' forms. This is consistent with properties #2 and #3, but again  
makes certain types of mutually recursive definitions inexpressible.

If inner `define-syntax' forms are not allowed at all and property #3  
is held, property #2 can't be satisfied. I think this is a bad idea,  
personally. The consistency of inner `begin' and top-level `begin' is  
important in order to avoid confusion for macro authors and users.

I'm using the following as a test of property #1:

(let ()
   (define-syntax d
     (syntax-rules ()
       ((_ v) (define v (bar)))))
   (d foo)
   (define-syntax bar
     (syntax-rules () ((_) 1)))
   foo) -> 1 on a two-pass for internal definitions implementation

On an implementation supporting two-pass at the top level, the same  
program should run with the `let' swapped out for a `begin' for  
property #2 to hold.

Many implementations seem not to provide property #2. Consider:

(define-syntax foo
   (syntax-rules ()
     ((_) (define a 1))))

(let ()
   (begin
     (define a 2)
     (foo))
   (display a))

(display " ")

(begin
   (define a 2)
   (foo))
(display a)

(display "\n")

If the implementation displays `2 1', property #2 is violated. Many  
implementations treat top-level definitions differently from internal  
definitions in this fashion.

I'm using the following (complete program) to test property #3:

(begin
   (define foo (bar))
   (define-syntax bar (syntax-rules () ((_) 1)))
   foo) -> error if property #3 is held

Thus, we can categorize R5RS implementations by which of these  
properties they support:

Bigloo:                 3
Chez:                   1, 3
Chibi-Scheme:           1, 3
Chicken 4.1.0:          3
Gambit:                 None
Gauche:                 3 (According to recent mail from Shiro)
Larceny (R5RS):         3
MIT Scheme:             3 (Hygiene too broken to test #2)
Scheme48:               None
SISC:                   1, 3

Reports from other implementations are welcome.

--
Brian Mastenbrook
[email protected]
http://brian.mastenbrook.net/

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

Reply via email to