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