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