On 11/19/11 8:41 PM, Graydon Hoare wrote: > On 19/11/2011 4:02 AM, David Rajchenbach-Teller wrote: > >> Let's start with a little safety vocabulary, not specifically related to >> Rust. It is quite common to have two distinct words: "exceptions" for >> exceptional but expected behavior – that you typically want to catch – > > Heh. I appreciate the attempt to pick such terminology neutrally, but > "exception" and "catch" very plainly points towards the modern > typed-exceptions-with-unwind-semantics implementation. > > There are many other systems for error management: error codes, monads, > conditions-and-restarts, signals-and-handlers, etc. etc. > Unwinding-and-catching is a very specific strategy.
Let's switch vocabulary, then. "Report" and "Handle" are probably less
loaded with implicit meanings.
In my mind, that error codes and monads are effectively mechanisms for
type 1 report-and-handle (in addition to which, Haskell-style error
monads are effectively a different implementation of the unwind-and-
catch paradigm). Conditions-and-restarts are somewhat wilder but I would
essentially sit them under this umbrella – note that my knowledge of
conditions-and-restarts is extremely superficial.
Still in my mind, signals-and-handlers are on the other side, i.e. a
mechanism for failures.
> I point all this out because, quite a long while ago (before publishing
> anything), the Rust-on-paper design I worked on had a non-unwind-based
> condition system; errors represented an opportunity for a
> dynamically-scoped handler to offer recovery, *or fail*.
If you still have notes, I am interested in reading them.
Strike that, here they are :)
>> [...]
>
> Closures will be spawnable when we've implemented unique closures.
> That's a WIP, not a permanently-missing-feature.
Great :)
> Yes, and I am proposing one: pass *in* your handlers (or symbolic codes
> indicating handler-strategy) and have the callee handle *at the site of
> the condition*. Sorry if I wasn't clear enough about the implied use of
> tags I meant, up-thread.
>
> I'm serious. I've read and understood what you wrote above, so I'll ask
> you do the courtesy of reading and understanding the following
> paragraphs fully as well. I'm not writing them not to clobber you with
> the Obvious Superiority of my own beliefs -- they may well be wrong --
> just to clarify exactly what I'm suggesting, what I'd do as
> alternatives, and why.
Hey, don't worry, I love brainstorming and learning new stuff :)
> The old Rust condition system was modeled on the condition system in
> Mesa. [...]
Can I assume that your example is actually too short to demonstrate the
meaningful difference with C++/ML-style exceptions and that the
following would also work?
fn foo(fname: str) -> uint {
try {
let x = os::open(fname);
ret mylib::get_some_uint_property(x);
} handle os::file_not_exist(str filename) -> file {
ret os::create(fname);
}
}
> I found this argument compelling. So much so I'm probably exaggerating
> or mis-stating the arguments a bit. But it lead me to reflect a bit more
> on the *realistic* uses of exceptions I've seen in programs, and found
> myself unable to debate it: most catch clauses I see do one of a small
> number of very predictable things: ignore, retry, hard-fail, log, or try
> one of a very small number of alternative strategies to accomplishing
> the initial goal (create the file rather than open it, say) that the
> author of the callee could very well have predicted and codified in a
> small tag-set of extra arguments.
>
> So I removed the condition system from the design docs, and never
> implemented it. I propose structuring the libraries along these lines.
> That is, to have the callee authors actually think a bit about what an
> unusual-return means, which ways there might plausibly be for recovering
> from it, and take a tag or vec-of-tags carrying the preferred recovery
> strategy.
Ok, I now get what you meant with "wonderful tag things". I hope you
will forgive me for misunderstanding your previous e-mail, it was a tad
elliptic :)
This sounds interesting, and it might work, but I have the intuition
that this would not be precise enough.
Still, as the ground has shifted a little since the start of this
thread, I would like to sum up the current setting.
If I understand correctly, Rust 0.x will offer:
* tasks that are lightweight enough that we can theoretically afford to
launch as often as we want just for error-handling;
* tasks that are first-class.
In addition, I am nearly certain that we wish to be able to display a
different error message to handle, say, a failure of a module due to a
network error or a failure of the same module doing exact the same thing
but due to a disk error. Therefore, I also understand that:
* `fail` or some variant thereof can actually report a failure reason,
(presumably as task-bound value with type `any`)
If so, in effect, we already have Report-and-handle, and more precisely,
C++/ML-style type-safe-modulo-dynamic-typing exceptions, with
performance comparable to C++ exceptions.
And in that case, I have some difficulty finding out exactly which case
remain to be covered by the library design you detail above.
Could you provide a few examples before I answer the following?
> If this fails to hold together and we really, really have to revive some
> kind of structured at-a-distance recovery system, I'm going to suggest
> going back to the Mesa-like signal scheme I sketched out earlier (and
> above). The main (substantial!) advantage it offers is that recovery
> paths cause no actual unwinding-or-destruction -- recovery occurs
> effectively "at the signal site" -- so there's no question of
> perturbation of the typestate. Unwinding still only happens during
> failure. The handler is invoked like any other function and if it
> succeeds the unwinder is never even involved. IMO it's much tidier than
> try/throw/catch and/or monads-by-macros.
Thanks for your detailed answer,
David
signature.asc
Description: OpenPGP digital signature
_______________________________________________ Rust-dev mailing list [email protected] https://mail.mozilla.org/listinfo/rust-dev
