Scope boxes(was: Announcing E 0.8.4: The Birthday Release)
Mark S. Miller
markm@caplet.com
Thu, 24 Jun 1999 12:03:05 -0700
At 04:47 PM 6/1/99 , Dan Bornstein wrote:
>... I can't help adding at least a few more comments,
>the first of which is: Please update the E Syntax and E Kernel cheat sheet
>on the erights.org website.
[+] Mostly done.
These now point at more up to date material, but more writing & updating is
still needed.
>My firm belief is that you should have exactly one primitive per primitive
>concept. As a particular example, if you don't want to force all new scopes
>to come with a closure (i.e. as part of your lambda equivalent), then my
>take is that you need a separate scope primitive which does nothing but
>that, and *not* that you should have multiple primitives which all (in
>addition to whatever else they do) introduce a new scope. In this case, I'd
>say that your lambda primitive *shouldn't* introduce a new scope.
[+] Probably good, but more complex to do than you may think.
In going through http://www.erights.org/elang/blocks/index.html , but
looking only at the kernel subset, I see 4 separate kinds of scope boxes:
1) Simple curly-enclosed nested expression, as in
The nested block expression
http://www.erights.org/elang/blocks/nestedExpr.html
The else part of an if-then-else
http://www.erights.org/elang/blocks/ifExpr.html
The body of a (no hatch expression) loop
http://www.erights.org/elang/blocks/loopExpr.html
The attempt part of a try-catch or try-finally
and the finally part of a try-finally
http://www.erights.org/elang/blocks/tryExpr.html
2) A paren-enclosed guard expression and a following curly-enclosed expression
The if-then part of an if-then-else
http://www.erights.org/elang/blocks/ifExpr.html
3) A pattern and a following curly-enclosed expression
The escape expression
http://www.erights.org/elang/blocks/escapeExpr.html
The catch part of a try-catch
http://www.erights.org/elang/blocks/tryExpr.html
The match clause of an object expression
http://www.erights.org/elang/blocks/defObject.html
section "Matching Messages"
The match clause of a plumbing expression
http://www.erights.org/elang/blocks/defPlumbing.html
4) A verb & a paren-enclosed parameter-list, and a following curly-enclosed
expression
The method clause of an object expression
http://www.erights.org/elang/blocks/defObject.html
For occurrences of case #1, I could probably reuse the HideExpr parseNode
type as the scope-box component of the other four occurrences.
For case #3, I could probably reuse the MatchNode type.
For case #4, my MethodNode type is doing only this one job, so we're done.
For case #2, making the scope box a separate object seems like overkill.
I'm inclined to let IfExpr continue to handle the if-then scope box directly.
As we'll see in later replies, this does interact with the parse-tree
(really AST-tree) discussion. But does this kind of
scope-box-representation reuse seem like an improvement to everyone?
>>>* visitEscapeExpr: This is call-with-current-continuation, right? So,
>>>the surface syntax:
>>>
>>> escape <hatch> { <body> }
>>>
>>>should be expandable to a simple method call which passes a thunk
>>>constructed from the body:
>>>
>>> callWithCC (def _(<hatch>) { <body> }})
>>
>>[-] Fails the above criterion.
>>Perfect example of where I think it's easier to teach a primitive special
>>form than a primitive function combined with an introduced closure.
>
>[#] I have no problem with your analysis, assuming you intend never to
>expose the underlying callWithCC to the programmer. However, by doing that,
>you are making certain control flow constructs more difficult to express.
>Admittedly, I haven't had a *lot* of need to use callWithCC where the
>function wasn't statically defined in-place, but I personally don't want to
>deny anyone that possibility.
[+] I do, in fact, intend never to expose a more primitive call/cc.
In Scheme terminology, E's continuations are only dynamic extent. (For
everyone else: E's escape hatches may only be validly used until their
creating stack-frame context exits.) This is a good idea on several
grounds, but a sufficient reason is this allows a straightforward
implementation of E's call stack in terms of a conventional implementation
language's call stack. E's current implementation maps to Java is exactly
this way, and this seems essential for E's easy intercallability with Java.
Given that continuations are only dynamic extent, what could you more easily
write with call/cc than with escape?
Sorry for the latency,
--MarkM