[e-lang] Remaining semantic issues
Kevin Reid
kpreid at attglobal.net
Mon May 30 23:55:50 EDT 2005
On May 30, 2005, at 18:46, Mark Miller wrote:
> Kevin Reid wrote:
>> This raises interesting issues in relation to exception types. Most
>> usages of exception types can be replaced with separate ejectors -
>> but should they be?
>
> If the purpose of the exception types would be to enable the caller to
> dispatch on these types, in order to react differently to different
> exceptions, then yes, these should be done with ejectors or ejectoids
> instead.
I disagree. For example, I just recently wrote an interface to the
POSIX read() system call:
to read(maxOctets, eofEjector, errorEjector)
There are at least three different errors (not counting EOF) that
read() may return, ignoring the ones that result from memory errors.
Does it make sense to write read/5, and require the client to supply
three almost-but-not-quite-identical ejectors?
One could argue that since these are ejectors, it should just return
errno through the ejector, not using exception objects at all; but that
prevents using the standard optional-ejector tools - throw.eject()
can't be used to automatically fall back to (sealed) regular throwing.
It also reduces composability.
I think that there are cases where exception typing is even more the
obviously right solution, that only come up in complex situations - and
most of the E code written so far is trivial WRT necessary error
handling.
Also: EIO streams are written to have a single 'terminator' which is
resolved to a broken reference upon failure. It will surely be useful
to distinguish types of failure there, and so we need an exception type
system for that.
In general, it seems wrong to limit kinds-of-failure to being
represented as flow control and not data.
As a proof that it is *possible* to design an exception type system
that works without any particular pre-arrangement or global definition
of exception types, see my old message:
http://www.eros-os.org/pipermail/e-lang/2004-May/009822.html
>> Also, we need some way for E-defined objects to throw exceptions with
>> custom data fields, for when the failure needs to be described for
>> code that intends to handle it.
>
> Not if failures which should be handled are instead done with ejectors
> or ejectoids rather than normal exceptions.
Again, I think that these features are critical in some cases, and we
shouldn't throw them out just because we can do the trivial cases in
other ways.
(Also, your statement seems to me to to be confusing varieties of
object (exceptions) with varieties of nonlocal exit (throw()).)
I have at least one use case for data fields in exceptions in the
E-on-CL libraries:
Map#diverge/2 is implemented in terms of FlexMap#putAll/3. In the event
that there are duplicate keys after the key guard has coerced the keys,
it would be useful for the exception message to state what key is the
duplicate. However, this is not yet possible, as the exception provided
by putAll gives only a string description talking about keys "already"
in the map.
>> Also, I don't remember whether I mentioned this before:
>> We have this model of calling a provided object in order to perform
>> the nonlocal exit desired by the caller. But there is nothing that
>> *requires* the object-in-role-of-'ejector' to return (other than the
>> throw.eject convenience function).
>> An object could accept either an ejector *or* a function that returns
>> a value indicating how to handle the situation. Or the "ejector"
>> could perform a normal return to indicate "ignore this" - say, for a
>> warning.
>> This gives us equivalent power to Common Lisp's conditions and
>> restarts.
>> I should explain this in more detail and give examples, but I want to
>> get this message sent now. If I don't, feel free to remind me.
>
> collection.fetch/2 already uses this pattern, but the argument is
> described as a thunk rather than an ejector. I think this strikes the
> right balance. When the callee describes the argument as an ejector
> (or optEjector), then the callee should generally use throw.eject/2,
> and the caller should generally assume nothing useful will result if
> they pass in a pseudo-ejector which returns. Otherwise, the API should
> not describe the argument as an ejector.
Yes, this is clearly going beyond ejectors. But I think we should think
about the fact that these patterns are possible, and perhaps work out a
common concept/'supertype' of maybe-exiting callbacks.
However, if this affects E itself at all, it's a higher-level library
issue, and definitely not a kernel language issue, so we don't need to
think about it right now.
--
Kevin Reid <http://homepage.mac.com/kpreid/>
More information about the e-lang
mailing list