On Sep 15, 2009, at 12:14 PM, Ray Dillinger wrote:

> I don't think so.  "error, attempt to define b more than once" is
> consistent, but "error, attempt to use b before its definition"
> is not.

Fine. I was at least attempting to give the option of allowing users  
to use `define' for redefinition of existing top-level `define's when  
it makes sense.

> There is no mutation involved in the above code snippet.  What we
> have here is a conflation of binding and sequencing. BEGIN is
> properly a sequencing primitive, and as such there is no good reason
> why it needs to have any effect on scope.
>
> On the contrary, if BEGIN establishes a scope, then firstly it
> is redundant and should be eliminated because the only semantics
> it could then express are expressible by one of the various let
> and let-foo forms.

I'm not expecting `begin' to establish a scope itself.

The mental model I'm using for this is that `define' and `define- 
syntax' return multiple syntactic values. The `begin' syntax  
aggregates these values, and returns them upwards. At some point, they  
are returned to a syntactic continuation which effectively establishes  
all of the bindings in parallel. Expressions in the `begin' are  
treated as bindings of introduced names.

Given that individual top-level forms in the REPL can't establish  
multiple bindings in parallel, who's receiving those multiple  
syntactic values? You could imagine the REPL in this model as an ever  
nested sequence of LET forms:

(let ()
   *first user input here*
   (let ()
     *second user input here*
       (let ()
         *third user input here*
         ...)))

In this case, all of the bindings returned by any individual form  
entered at the REPL are established in parallel, and multiple  
individual forms establish bindings sequentially.

This model provides a consistent explanation for the semantics of  
`begin' as an aggregator of multiple syntactic return values creating  
bindings which are always established in parallel (as via `letrec*').

You could instead treat the multiple values received as being  
individual inputs at the REPL (the "splicing construct" model), but as  
I've argued elsewhere, this makes it difficult to know what to expect  
when writing `begin'. And `begin' isn't a splicing construct in  
general: (+ (begin (define foo 3) foo) 4) is not the same as (+  
(define foo 3) foo 4).

> Secondly, the language needs a primitive for bundling multiple
> forms which does not establish a scope, for purposes of allowing
> macros to expand into multiple forms (typically definitions)
> when those forms must be in the same scope as the call site.

I think I've been less than clear about this in my past emails: I'm  
not proposing to get rid of this. I'm only talking about the  
interpretation of a top-level `begin' at the REPL.

> Absolutely.  It is not at all screwy to have (and need!) a single
> macro invocation to expand into multiple definitions.  See the
> highly useful object library 'Meroon,' which was written by
> Christian Queinnec and featured in his excellent book
> (_Les_Langages_Lisp_ in French, _Lisp_In_Small_Pieces_ in English)
> for a widespread example of macros in a library that a lot of
> people actually do use.  It would break horribly if begin
> contained its definitions in a local scope, and more importantly,
> there would be no way to fix it because without an open-scoped
> bundling primitive there would be no way left to implement it
> in Scheme.

Actually, greater consistency for authors of such libraries is what  
I'm trying to argue for.

--
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