|
From: Donal K. F. <don...@ma...> - 2008-11-23 16:37:15
|
Twylite wrote:
> I think it's time for a summary of where we are on the try/catch/finally.
[...]
> (f) Have reasonable performance, at least for the common cases.
Some notes on this: I plan to make [try] bytecode compiled as it has
script bodies. But it is highly likely that I won't have time to do this
before 8.6b1! To facilitate this, only requiring equality- or
glob-matching (and having it be compile-time decidable) will be good.
Please do not require lots of nested parsing of lists and things like
that either (especially lists of scripts) since working with those
things in the compiler is really unpleasant.
For the b1 release, a pure Tcl scripted version will be good enough.
> (c) A [try] statement is going to look more like an "if {} then {} else
> {}" than a "switch { case {body} case {body} }". The former seems to be
> preferred by everyone involved in the discussions.
In particular, it's much easier to compile.
> (a) In general the matching of exceptions (return code) and errors
> (errorCode where the return code is TCL_ERROR) are separate concerns.
> It makes sense to exploit this by using a fast/exact match against the
> return code first (meeting the performance requirement) followed by a
> slower match against the errorCode.
We'll probably build a jump table.
> (b) When matching against errorCode:
> (i) There is (largely) consensus that basic pattern matching is "good
> enough" "for now". Basic pattern matching may be defined as prefix
> matching, glob matching against errorCode (as a string), or an
> element-wise list-glob match against errorCode (as a list). In short
> there is no agreement on the right way to do this.
I think we'll find that glob-matching is good enough. Almost everyone
will use it for prefix matching; Tcl's glob-matcher is good at that.
> (ii) There is also no guarantee that a match against errorCode will be
> adequate in the future. For example an OO-style error object may be
> developed.
Out Of Scope! If someone needs something that complicated, they'll have
to write their own code.
> (iii) An [expr]-type match is the most flexible but the lowest
> performance (and potentially ugliest syntax); as such it is not suitable
> (at least not as a default).
Need I repeat myself? OOS!
> (iv) Delegating to [switch] for matching is a nice compromise of
> performance and flexibility (and reuses existing functionality), but
> brings with it the baggage of the [switch] command's interface.
If we require [switch] for the normal case, we might as well not use
[try] at all. The purpose of [try] is to reduce baggage for important
classes of error handling.
> (c) The only thing we _can_ be sure of is that whatever we choose now
> will be inadequate in some what, implying that the syntax of [try] must
> contain provision for future extension.
> (d) Taking (c) to its logical conclusion, [try] must be specified and
> implemented to support user-selectable pattern matching. It is possible
> to have the matcher selected for the [try] as a whole, or per handler,
> and there are pros and cons to each approach.
>
> In terms of (d) my personal preference is to specify the matcher per
> handler. It is difficult to predict how different packages/libraries
> may approach error handling, both now and in the future (e.g. a future
> move from -errorCode to an OO-style error object). If the matcher is
> selected for the [try] as a whole it may only be possible to support
> disparate error handling styles by using the most flexible and complex
> matcher (say [expr]-based), which could be an unnecessary complication.
> The same holds now for integrating with legacy code that only produces
> meaningful error information in the result.
I write quite a lot of Java code, and I don't think there's anything
really worth it to be gained from OO exceptions. A list that folks can
match against is good enough, and they can add their own complexity if
they really want. We're building a bikeshed, not an aircraft carrier!
> On
> the issue of ordering, left-to-right is the only order than makes sense
> for [expr]-based matching, and is the norm in other languages.
Not all. C is unspecified. But Tcl is very much left-to-right.
> The implementation will probably provide the following handlers by
> default (users can implement their own):
> - -like for glob matching against errorCode as a string (perhaps -glob?)
> - -llike for element-wise list-glob matching against errorCode as a list
> - -expr for expr-based matching (with access to return code, result &
> options dict)
Too complicated by far. Glob is enough. If people want to match by ouija
board, they can write their own command. (To be clear, that's an example
of a carrier deck, undoubtedly useful to some but not part of any
sensible bikeshed...)
> I feel that this proposal meets the requirements with the greatest
> flexibility and the least ambiguity. But of course that's my opinion.
I feel that you're chasing off in the wrong direction. Try this:
try script ?as {msgvar optvar}? ?handler...? ?finally script?
Each handler is one of these:
on code script
trap glob script
Where 'code' is any numeric code or named alias or '*' (to mean any) and
'glob' is a pattern according to [string match] to be checked against
the errorcode with an implied code of 'error'. Only errors in the
initial script are trapped; errors in any handler replace the original.
The finally script is run after all else, and in all cases (except for
interpreter deletion, execution cancellation or resource exhaustion) and
errors in *it* will replace all others. All handlers except the last one
may be the string literal '-', which means use the one following; the
last one must not be that, and the finally clause is not a handler.
I'll not argue over the names 'on' or 'trap'. Expect a fight on anything
else as this is probably as complicated as it is sensible to go. :-)
Note that there's no need for an explicit rethrowing command (can do
that with [return] and the options dict) and there's no need for an
explicit variable for the code; it's in the options dict.
Donal.
|