n Mon, 19 Apr 2004 15:36:14 +0000, Anton van Straaten wrote:
It can be done only by delegating the choice to another concept, like
"BEGIN combines a sequence of forms" and "to combine forms in the context
of a toplevel means [...], for internal definitions it means [...], and
for expressions [...]".
There is no preexisting concept which gives all meanings of combination,
it exists for BEGIN only.
I didn't deny that the interaction of BEGIN with toplevel definitions and
internal definitions is similar enough that they can be even explained
using the same words. But it's only a part of BEGIN. Expression-BEGIN is
What is the fourth BEGIN?
How it can be described? Does it lead to the same set of valid programs
with the same meaning?
It's not enough to say what is valid inside BEGIN. You must also specify
how the meaning of BEGIN is constructed from the meanings of its arguments,
or how is it transformed syntactically, whichever is more convenient.
There is little left after removing the context-sensitive part! What
is valid inside BEGIN - fine, this is analogous; but the meaning as
a definition and as an expression are very different.
If I designed Scheme, I would do this:
1. Separate expression-BEGIN and definition-BEGIN. The name BEGIN would
go to the expression BEGIN, the other could be GROUP or something.
2. Introduce LETREC* and change the meaning of internal definitions from
LETREC to LETREC*.
3. Allow internal definitions in BEGIN. In an alternative description of
the same overall effect, the semantics of internal definitions would
be described at BEGIN only, with all other cases being rewritten into
4. Allow expressions among internal definitions. The result of such
expression are ignored. Declare that all forms in a body except the
last are internal definitions, and the last one is an expression.
The effect is quite consistent, much more regular than with R5RS Scheme.
The semantics of toplevel and internal definitions is completely analogous.
GROUP means the same thing in both.
BEGIN also means only one thing, and is completely equivalent to ((let ()
arg ...)), including the criteria what is allowed inside. It's simpler to
take BEGIN as the primitive which introduces internal definitions and
describe the let body and other bodies in terms of BEGIN.
Note that GROUP and BEGIN can now be used with the same context with a
different meaning: GROUP forms a compound definition, with all definitions
inside being exported, while BEGIN forms an expression with the definitions
visible only inside it.
I think the only drawback of this proposal, apart from being different
from what we have now, is that some people dislike internal definitions
and try to make them as little used as possible.
I suspect that the mixed semantics of current BEGIN results from Common
Lisp's PROGN, which can be used both for expressions and for toplevel
definitions because Lisp toplevel definitions are almost expressions,
evaluated for the side effect of rebinding a symbol! That's why the same
thing for both seems natural in Lisp. But a Scheme definition is not an
expression with ignored result and side effect; it's a binding construct,
a separate concept.
__("< Marcin Kowalczyk