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