[E-Lang] pending revision of E in a Walnut
Mark Seaborn
mrs35@cam.ac.uk
Sun, 26 Aug 2001 23:57:19 +0100
"Mark S. Miller" <markm@caplet.com> writes:
> when (xVow) -> done(x) {
> # x in scope
> doSomething(x)
> } catch prob {
> # x not in scope. prob in scope
> handle(prob)
> }
> Proposal: If doSomething(x) does throw a problem, catch this problem in the
> catch clause as well -- binding prob and calling handler. Since the "x"
> parameter of "done(x)" can be any pattern, the catch clause can catch its
> failure to match as well.
A problem I have with exception-handling constructs is that they tend
to be too liberal in where they catch exceptions from. In OCaml, I
tend to use the idiom:
match (try `Success (f())
with exn -> `Failure exn) with
| `Success x -> success x
| `Failure exn -> failure exn
I could write
try success (f())
with exn -> failure exn
which would be more concise, but might result in `success' being
partially executed and then `failure' executed, which could be
harmful. I really want to catch exceptions only from the expression
`f()', and I want only one of `success' or `failure' to be called.
So this change in the semantics of `when' wouldn't always be
desirable, since it makes it harder to do the sort of thing the first
fragment of OCaml does.
On a related topic, a common idiom in E seems to be to create
(promise, resolver) pairs in order to return the promise immediately
and resolve it in the `done' or `catch' clause of a `when' expression.
But since `when' currently doesn't return any interesting value
(correct me if I'm wrong on this), why not make `when' return a
promise for the value that is returned by the `done' or `catch' clause
(with the promise becoming broken if the clause executed throws an
exception)? In other words, make
when(X) -> done(x) { Y }
catch e { Z }
give the behaviour currently given by
def [promise, resolver] := PromiseMaker()
when(X) -> done(x) {
try { resolver resolve(Y) }
catch e { resolver smash(e) }
}
catch e {
try { resolver resolve(Z) }
catch e2 { resolver smash(e2) }
}
promise
(Except that exceptions should not be caught when calling resolver's
smash method, only when evaluating Y or Z, but this is fiddly to do as
explained above. Also the expansion of `when' could probably remove
the use of `try' by using eventual sends for turning control-flow
exceptions into data-flow exceptions.)
Using PromiseMaker explicitly creates the risk that a resolver will
never get called, which could cause datalock. Extending the behaviour
of `when' gives a way of eliminating the use of PromiseMaker, reducing
that risk and making code shorter and clearer.
This extension provides a path for exceptions from the `done' and
`catch' clauses to flow along. If no result flows out from the `when'
expression, odds are that those exceptions don't make any difference
and don't need to be reported.
--
Mark Seaborn
- mseaborn@bigfoot.com - http://www.srcf.ucam.org/~mrs35/ -
Out, damned tagline! out, I say!