|
From: Twylite <tw...@cr...> - 2008-11-23 17:06:09
|
Hi, > Don't entirely agree with this. I don't believe we need to care about > inconsistent sets of vars being defined after the try -- it's not a > problem for [if], [switch], and every other control structure, so I > don't believe we need to give it special consideration here. Agree > though that it is generally more useful for whatever pattern matching > mechanism is used to be called with a set of pattern/script pairs and > the variables already set-up in the callers scope. Whether that means > binding the vars for the entire try statement or once per exception > code is a matter of choice. Either seems acceptable. The difference being that in the case of [if] or [switch] the executed body defines the vars; in this case the [try] itself defines the vars. Semantics. The stronger argument is the performance impact of bringing per-handler vars into scope and back out of scope each time. >> (e) A [switch]-like "fall through to next statement" would be a >> nice-to-have. > Clarifying this -- we want the ability to specify the same script for > multiple patterns (and possibly multiple exception codes). The switch > approach is one way. Cool. >> 3. Matching >> (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. > If adopting some novel pattern mechanism, then there is the further > question of whether to special case that in [try] or to extract it out > into a separate command (and separate TIP). So that we have [catch], [try], [try2], ... as we discover new and different needs for exception handling? No thanks. We should either get [try] sufficiently right now (which is closer to 99% than 80%) or make it extensible. Preferably the latter since we don't know what is 99% right. >> (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. > This depends how it is done, and how it is documented. You can > delegate to [switch] either implicitly or explicitly (as a > -matchcommand) and still avoid acquiring [switch]'s interface. You > just document that pattern-matching is handled by [switch] and that as > far as [try] is concerned the patterns are just opaque data that it > passes on. Introducing an explicit option for this enhances this > rationale, as then the pattern matcher is just another callback. What > we definitely don't want to do is introduce [switch]'s various > options, like -nocase, -regexp etc as options of [try]. That would > constrain the implementation and be a mess. A callback solution avoids > this as the options can be specified as part of the callback command, > rather than as part of the try command. I was meaning a [try] that uses [switch] implicitly. You would need something in the interface of [try] that would configure the [switch], otherwise you are limited to some predetermined configuration (like -glob --). Agreed that a callback gets around this, and discussed in (c) and (d) below. >> (c) The only thing we _can_ be sure of is that whatever we choose now >> (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 > I'd be interested to see the interface proposed for this. Clearly the > most flexible approach is to allow an arbitrary script to do the > matching, but then we end up right back at the beginning of this > discussion where [try] just does exception-code dispatch and leaves > everything else up to a script. I believe we've ruled that option out, > as it violates requirements 1.b and 1.c. I believe the interface I proposed does not violate (1.b), and provides an acceptable compromise on (1.c). >> (b) The behaviour of the [try] should be predictable and conform to the >> principle of least surprise. On particular consequence of this is that >> matchers must consider handlers/errorPatterns in left-to-right order, >> and all handlers should be executed in the same fashion (implying that >> the [try] rather than the matcher should execute the handler body). 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. > I don't believe [try] has to execute the bodies. All it has to do is > ensure that any option/result variables are defined in the calling > scope when that script runs. For example: There are a bunch of other things [try] has to do, including catching errors off the handlerscript (and match command, for that matter) in order to chain the errors, execute the finally script, etc. Having the match command execute the body means that its not just a match command but a fully fledged control structure, it must behave in a way that is predictable to the [try] command (i.e. [try] needs to make certain assumptions about what it will do), and the [try] cannot distinguish between a failure in the match command and a failure in the handlerscript. It also has the potential to make the errorInfo very ugly -- you will see an exception in a handler in a matchcommand in a try. If you try to use a [return -level] to avoid this you will end up with unsafe nesting and/or making assumptions about the internals of [try]. In your proposal you also talk about the match command adding a default -- this would not work if [try] is expected to chain errors, as [try] would catch the default (assumedly rethrown) error and chain it to itself (i.e. the error that [try] knows about). Any way I look at it, having the match command execute the body joins together separate concerns (matching, and execution), and there are only two arguments for this: (1) Performance. The largest number of exception handlers I've ever seen attached to a single try is 5 or 6. It there ever going to be a large enough number that the performance difference will be significant? (2) Specifically allowing the order of matching to be determined by the match command. > I also believe the order in which to consider patterns should be left > to the match command. I think non-determinism in the syntax of a language is a very bad thing. Notice that even [switch] is documented as: "The switch command matches its string argument against each of the pattern arguments in order", so the behaviour is deterministic and unsurprising from a user perspective, and a linear trawl would be no slower than a matcher that uses [switch]. In order to ensure the performance of the "common case" the most common matcher (probably "-like") could be hard-coded into the [try] implementation. Regards, Twylite |