You can subscribe to this list here.
| 2000 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
(19) |
Jul
(96) |
Aug
(144) |
Sep
(222) |
Oct
(496) |
Nov
(171) |
Dec
(6) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2001 |
Jan
(4) |
Feb
(4) |
Mar
(9) |
Apr
(4) |
May
(12) |
Jun
(6) |
Jul
|
Aug
|
Sep
(1) |
Oct
(2) |
Nov
|
Dec
|
| 2002 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
(1) |
Jul
(52) |
Aug
(47) |
Sep
(47) |
Oct
(95) |
Nov
(56) |
Dec
(34) |
| 2003 |
Jan
(99) |
Feb
(116) |
Mar
(125) |
Apr
(99) |
May
(123) |
Jun
(69) |
Jul
(110) |
Aug
(130) |
Sep
(289) |
Oct
(211) |
Nov
(98) |
Dec
(140) |
| 2004 |
Jan
(85) |
Feb
(87) |
Mar
(342) |
Apr
(125) |
May
(101) |
Jun
(60) |
Jul
(151) |
Aug
(118) |
Sep
(162) |
Oct
(117) |
Nov
(125) |
Dec
(95) |
| 2005 |
Jan
(141) |
Feb
(54) |
Mar
(79) |
Apr
(83) |
May
(74) |
Jun
(125) |
Jul
(63) |
Aug
(89) |
Sep
(130) |
Oct
(89) |
Nov
(34) |
Dec
(39) |
| 2006 |
Jan
(98) |
Feb
(62) |
Mar
(56) |
Apr
(94) |
May
(169) |
Jun
(41) |
Jul
(34) |
Aug
(35) |
Sep
(132) |
Oct
(722) |
Nov
(381) |
Dec
(36) |
| 2007 |
Jan
(34) |
Feb
(174) |
Mar
(15) |
Apr
(35) |
May
(74) |
Jun
(15) |
Jul
(8) |
Aug
(18) |
Sep
(39) |
Oct
(125) |
Nov
(89) |
Dec
(129) |
| 2008 |
Jan
(176) |
Feb
(91) |
Mar
(69) |
Apr
(178) |
May
(310) |
Jun
(434) |
Jul
(171) |
Aug
(73) |
Sep
(187) |
Oct
(132) |
Nov
(259) |
Dec
(292) |
| 2009 |
Jan
(27) |
Feb
(54) |
Mar
(35) |
Apr
(54) |
May
(93) |
Jun
(10) |
Jul
(36) |
Aug
(36) |
Sep
(93) |
Oct
(52) |
Nov
(45) |
Dec
(74) |
| 2010 |
Jan
(20) |
Feb
(120) |
Mar
(165) |
Apr
(101) |
May
(56) |
Jun
(12) |
Jul
(73) |
Aug
(306) |
Sep
(154) |
Oct
(82) |
Nov
(63) |
Dec
(42) |
| 2011 |
Jan
(176) |
Feb
(86) |
Mar
(199) |
Apr
(86) |
May
(237) |
Jun
(50) |
Jul
(26) |
Aug
(56) |
Sep
(42) |
Oct
(62) |
Nov
(62) |
Dec
(52) |
| 2012 |
Jan
(35) |
Feb
(33) |
Mar
(128) |
Apr
(152) |
May
(133) |
Jun
(21) |
Jul
(74) |
Aug
(423) |
Sep
(165) |
Oct
(129) |
Nov
(387) |
Dec
(276) |
| 2013 |
Jan
(105) |
Feb
(30) |
Mar
(130) |
Apr
(42) |
May
(60) |
Jun
(79) |
Jul
(101) |
Aug
(46) |
Sep
(81) |
Oct
(14) |
Nov
(43) |
Dec
(4) |
| 2014 |
Jan
(25) |
Feb
(32) |
Mar
(30) |
Apr
(80) |
May
(42) |
Jun
(23) |
Jul
(68) |
Aug
(127) |
Sep
(112) |
Oct
(72) |
Nov
(29) |
Dec
(69) |
| 2015 |
Jan
(35) |
Feb
(49) |
Mar
(95) |
Apr
(10) |
May
(70) |
Jun
(64) |
Jul
(93) |
Aug
(85) |
Sep
(43) |
Oct
(38) |
Nov
(124) |
Dec
(29) |
| 2016 |
Jan
(253) |
Feb
(181) |
Mar
(132) |
Apr
(419) |
May
(68) |
Jun
(90) |
Jul
(52) |
Aug
(142) |
Sep
(131) |
Oct
(80) |
Nov
(84) |
Dec
(192) |
| 2017 |
Jan
(329) |
Feb
(842) |
Mar
(248) |
Apr
(85) |
May
(247) |
Jun
(186) |
Jul
(37) |
Aug
(73) |
Sep
(98) |
Oct
(108) |
Nov
(143) |
Dec
(143) |
| 2018 |
Jan
(155) |
Feb
(139) |
Mar
(72) |
Apr
(112) |
May
(82) |
Jun
(119) |
Jul
(24) |
Aug
(33) |
Sep
(179) |
Oct
(295) |
Nov
(111) |
Dec
(34) |
| 2019 |
Jan
(20) |
Feb
(29) |
Mar
(49) |
Apr
(89) |
May
(185) |
Jun
(131) |
Jul
(9) |
Aug
(59) |
Sep
(30) |
Oct
(44) |
Nov
(118) |
Dec
(53) |
| 2020 |
Jan
(70) |
Feb
(108) |
Mar
(50) |
Apr
(9) |
May
(70) |
Jun
(24) |
Jul
(103) |
Aug
(82) |
Sep
(132) |
Oct
(119) |
Nov
(174) |
Dec
(169) |
| 2021 |
Jan
(75) |
Feb
(51) |
Mar
(76) |
Apr
(73) |
May
(53) |
Jun
(120) |
Jul
(114) |
Aug
(73) |
Sep
(70) |
Oct
(18) |
Nov
(26) |
Dec
|
| 2022 |
Jan
(26) |
Feb
(63) |
Mar
(64) |
Apr
(64) |
May
(48) |
Jun
(74) |
Jul
(129) |
Aug
(106) |
Sep
(238) |
Oct
(169) |
Nov
(149) |
Dec
(111) |
| 2023 |
Jan
(110) |
Feb
(47) |
Mar
(82) |
Apr
(106) |
May
(168) |
Jun
(101) |
Jul
(155) |
Aug
(35) |
Sep
(51) |
Oct
(55) |
Nov
(134) |
Dec
(202) |
| 2024 |
Jan
(103) |
Feb
(129) |
Mar
(154) |
Apr
(89) |
May
(60) |
Jun
(162) |
Jul
(201) |
Aug
(61) |
Sep
(167) |
Oct
(111) |
Nov
(133) |
Dec
(141) |
| 2025 |
Jan
(122) |
Feb
(88) |
Mar
(106) |
Apr
(113) |
May
(203) |
Jun
(185) |
Jul
(124) |
Aug
(202) |
Sep
(176) |
Oct
(181) |
Nov
|
Dec
|
|
From: Twylite <tw...@cr...> - 2008-11-23 20:36:56
|
Hi,
> I don't think that actually matters. In what circumstance do you
> envision this causing a real problem?
>
I don't -- it's an understandability & readability thing. Everyone's
going to have their own take.
>> The stronger argument is the performance impact of bringing per-
>> handler vars into scope and back out of scope each time.
>>
> I don't see this point, could you elaborate? The vars only need to be
> defined once.
>
If the vars are defined per handler, and can be different per handler,
then multiple different variables must be brought into scope (and
possibly out again if you don't want them handing around if the handler
didn't match).
I think the confusion here is what constitutes a "handler" - according
to all my proposals a "handler" is (return code + optional more specific
pattern), but your recent proposal is (return code + pattern1 + pattern2
+ ...). Clearly there would issues of performance and dangling
variables in the case I am understanding, but not in the case of your
proposal.
> No -- I mean you would have [try] and some [lmatch] command.
>
Sorry - misunderstanding.
> I don't see why [try] has to know anything at all about it. It is
> just passed a callback that takes the errorcode and a list of pattern-
> >script pairs, and simply calls it, returning whatever it returns
> (including exceptions). All it needs to do is ensure any "finally"
> script runs.
>
Because [try] is a (core) command that is promising a particular
interface & behaviour, but the implementation cannot guarantee the
behaviour as it delegates too much to a matcher that _may_ be
implemented outside the core.
And because, as you highlight below, you have to identify and compensate
for the corner cases in the matcher.
> I don't see this as a problem. If [try] is documented as delegating
> to a match command then it makes sense for that command to appear in
> the stack trace. [try] can always pretty up the errorinfo if it helps.
>
> A simple equality check would avoid this (a Tcl_Obj pointer
> comparison). Alternatively, the default script can be manufactured to
> signal this special condition. It's a problem of implementation not
> interface.
>
All I'm saying is that rather than have the matcher actually execute the
script, it should return it (or the index of the script in whatever
list/dict was provided to the matcher) and allow the [try] to execute
the script directly.
>> (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?
>>
> Possibly, in generated code. E.g. there are quite a large number of
> possible HTTP return codes. If these got put into an errorCode {HTTP
> 302 /redirected.html} then I can quite imagine HTTP client libraries
> wanting large try statements and wanting fast lookup.
>
Fair case.
But how will they do it now? I would imagine most developers would
happily use a [switch], not realising that they are not getting O(1)
performance out of it.
>> 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
> This is the point -- the behaviour isn't non-deterministic as it is
> explicit what command is being used for matching, and the docs for
> that command specify the ordering used. Non-determinism doesn't
> require that [try] specify every last detail of execution -- it can
> happily delegate those responsibilities.
>
The point is that irrespective of whether you are using -glob, -regex or
-exact, you as a developer can scan the [switch] cases in left-to-right
order and know that the first match will be the one that will be used.
If [try] delegates its ordering then you cannot do this. You need to
know the behaviour of "try -command mymatcher".
Given "try -command oo_matcher { .... } on error SomeException { ... }
on error OtherException { ... }" it is reasonable to assume that you're
matching on the class of the exception object, but if OtherException is
a child of SomeException, which one will match? Language syntax should
enable you to determine that. Leaving it to a pluggable handler means
that a novice developer or maintenance coder needs to understand every
nuance of [try] and every matcher you use to understand the behaviour of
a rather elementary control structure.
Regards,
Twylite
|
|
From: Twylite <tw...@cr...> - 2008-11-23 20:16:57
|
Not to nitpick but ...
> It's too complicated. (Or not complicated enough since it doesn't permit
> arbitrary matching of arbitrary subsets of options. After all it's
> *totally vital* that I be able to use soundex matching on the error
> message when it's on the 13th-22nd line of the body while dealing with
> some custom extra parameters!!! </sarcasm>)
as {em opts} on error -expr { [dict get $opts -errorline] >= 13 && [dict
get $opts -errorline] <= 22 && [soundex match $PATTERN $em] } { ... }
:)
Twylite
|
|
From: Donal K. F. <don...@ma...> - 2008-11-23 19:33:01
|
Andreas Leitgeb wrote: > Maybe it falls into the 100- "80+%", but it just matches the > structure of errorCode better than string-based globbing. It's also massively more complicated to implement and document. Since I'm the maintainer of the relevant area, I think those sorts of issues are important! > Even if it is not considered for 8.6b1, I do hope it will > be in for 8.6. You seem to be acting under a misunderstanding about the difference between 8.6b1 and 8.6.0. It is the policy of the TCT and Maintainers that new features not be introduced to the API during the beta or release parts of the cycle. Donal. |
|
From: Andreas L. <av...@lo...> - 2008-11-23 19:17:21
|
On Sun, Nov 23, 2008 at 07:59:25PM +0200, Twylite wrote:
> The errorCode list is meant to be a hierarchy of error classes. If you
> specify the first element as "ARITH MATRIX" then it isn't a subclass of
> ARITH (which would be [list "ARITH" "MATRIX"]).
Yes, Donal made this clear, too, meanwhile.
I retract that particular example, but come up with a different
one instead.
Imagine an errorcode similar to
CHILDSTATUS pid code
except with further data after the code:
MYCHILDSTATUS pid code exectime text
which would also return the process's total execution time
in microseconds and some free text as well. It doesn't get thrown
now, but it sounds reasonable to be possibly thrown by some
user-defined "spawn" command.
With my suggestion of list-patterns, I could
handle {MYCHILDSTATUS * 1} {...}
and thusly safely handle exactly the cases where the
exit code was 1. (The list-pattern is shorter than
the code, and this would be defined to mean, that only
the first [llength $pattern] elements of errorCode
play a role, all others matching trivially.)
Maybe it falls into the 100- "80+%", but it just matches the
structure of errorCode better than string-based globbing.
Even if it is not considered for 8.6b1, I do hope it will
be in for 8.6.
|
|
From: Andreas L. <av...@lo...> - 2008-11-23 18:28:40
|
On Sun, Nov 23, 2008 at 05:47:25PM +0000, Donal K. Fellows wrote: > What are you talking about? Apart from the fact that [list "ARITH > MATRIX" foo bar] isn't generating an ARITH code in the first place, Hmm, ok, so it isn't. I envisioned it to be. > Subtype descriptors are separate words, as you would know if you'd ever > actually looked at them! Here's a couple of real examples: I made a distinction between actual error codes (like ENOENT) and sub-subsystem specification. I now see that such a distinction doesn't really make sense. > You're wrong. You're right. But with all my examples being voided, I still have a bad feeling about applying text-operations on lists. I guess, I'll have to live with it. |
|
From: Donal K. F. <don...@ma...> - 2008-11-23 18:04:48
|
Twylite wrote: > Are you _sure_ glob is enough? I'm not. So I want a syntax that > doesn't preclude extension (in a pretty) to handle other options in the > future. And I'd like a syntax that allows developers to create these > extensions outside the core, so that these options can evolve in future > rather than end up in a length discussion that really has few facts and > figures to back up things like "most developers" and "common case". I don't want any of that high-falutin' baggage. I do not think the practical use-cases justify it. > Versus: > on code ?-howtomatch whattomatch? script > > I cannot comment on the implications of byte-coding that, but I do feel > that it is more consistent (on error vs trap), more flexible, etc. It's too complicated. (Or not complicated enough since it doesn't permit arbitrary matching of arbitrary subsets of options. After all it's *totally vital* that I be able to use soundex matching on the error message when it's on the 13th-22nd line of the body while dealing with some custom extra parameters!!! </sarcasm>) I'll go with dealing with the 90% use-case. > Your proposal is of course extensible by adding new handler keywords in > future (assuming the TIP proposers at the time can agree on the > keyword), but this would have to be done in the core. Your proposal goes so far towards being flexible that it ceases to be practical. Cut out the complexity; it'll be good enough. Donal. |
|
From: Neil M. <ne...@Cs...> - 2008-11-23 18:04:19
|
On 23 Nov 2008, at 17:06, Twylite wrote:
> 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.
I don't think that actually matters. In what circumstance do you
envision this causing a real problem?
> The stronger argument is the performance impact of bringing per-
> handler vars into scope and back out of scope each time.
I don't see this point, could you elaborate? The vars only need to be
defined once.
>>> (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.
No -- I mean you would have [try] and some [lmatch] command.
>>> [...]
>> 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.
I don't see why [try] has to know anything at all about it. It is
just passed a callback that takes the errorcode and a list of pattern-
>script pairs, and simply calls it, returning whatever it returns
(including exceptions). All it needs to do is ensure any "finally"
script runs.
> 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].
I don't see this as a problem. If [try] is documented as delegating
to a match command then it makes sense for that command to appear in
the stack trace. [try] can always pretty up the errorinfo if it helps.
> 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).
A simple equality check would avoid this (a Tcl_Obj pointer
comparison). Alternatively, the default script can be manufactured to
signal this special condition. It's a problem of implementation not
interface.
> 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:
Yes, you can separate these concerns, of course. But neither of them
need to be handled by [try].
> (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?
Possibly, in generated code. E.g. there are quite a large number of
possible HTTP return codes. If these got put into an errorCode {HTTP
302 /redirected.html} then I can quite imagine HTTP client libraries
wanting large try statements and wanting fast lookup.
> (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.
This is the point -- the behaviour isn't non-deterministic as it is
explicit what command is being used for matching, and the docs for
that command specify the ordering used. Non-determinism doesn't
require that [try] specify every last detail of execution -- it can
happily delegate those responsibilities.
-- Neil
This message has been checked for viruses but the contents of an attachment
may still contain software viruses, which could damage your computer system:
you are advised to perform your own checks. Email communications with the
University of Nottingham may be monitored as permitted by UK legislation.
|
|
From: Twylite <tw...@cr...> - 2008-11-23 17:59:32
|
Hi, > Perhaps it's just me that I envision hierachies of error classes. > > Not being able to catch ARITH and all subclasses like a "ARITH MATRIX" > with the same clause - just because the latter has list-meta-syntax that > needs to be taken care of - feels just wrong to me. > The errorCode list is meant to be a hierarchy of error classes. If you specify the first element as "ARITH MATRIX" then it isn't a subclass of ARITH (which would be [list "ARITH" "MATRIX"]). > Otherwise we'd have to discourage use of spaces and all other > list-special characters in user defined errorcodes. > That's almost certainly not a bad idea. Regards, Twylite |
|
From: Twylite <tw...@cr...> - 2008-11-23 17:55:56
|
Hi,
> I'm not sure about this.
>
> try {
> open $filename w
> } as {code var} on ok {
> # (1)
> } on error {
> # (2)
> }
>
> In block (1), $var holds an open file handle;
> in block (2) it holds an error message.
>
This is of course what you get from [catch] at present.
> Personally I'd prefer having different variable names
> in the different branches:
>
Your objection has been forwarded to Fredderic and NEM.
This one here gone back and forth on Tcl-core more than once, and in
private discussions. Having the vars at the front of [try] reduces
repetition which keeps the look cleaner. It may also make
implementation simpler & more efficient depending on how we match
exceptions & errors. Having the vars with the handler improves
locality, and some developers find it more readable. Sounds like this
is a personal preference one that is going to be hard to resolve.
> It also unconditionally binds the variable 'code',
> which is unused and unneeded. (In blocks (1) and (2)
> you already know what $code is; outside of the [try]
> command you no longer care.)
>
As someone who uses "code" all over the place as a local variable, I'd
be really unhappy with a new control structure automagically defining
variables in my stack frame that I didn't tell it to (and I can't think
of any other Tcl command that does this).
> (I'm also somewhat alarmed at the growing complexity
> of the error matching facilities -- especially because
> I am not yet convinced that they will be useful in practice.
> I'd rather start with something braindead simple and
> add to it later. Features are easy to add, but
> incompletely baked features are very very hard to
> get rid of.)
>
I want a syntax that handles adding the features later without making
the [try] an ugly construct. I would _like_ a syntax that allows those
features to be added outside the core. At this point the core only
needs to provide glob-style matching for error codes.
Regards,
Twylite
|
|
From: Twylite <tw...@cr...> - 2008-11-23 17:50:09
|
Forgot:
> 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.
>
catch { return -code 5 FAIL } em opts
2
dict get $opts -code
5
?
|
|
From: Donal K. F. <don...@ma...> - 2008-11-23 17:47:31
|
Andreas Leitgeb wrote:
> Perhaps it's just me that I envision hierachies of error classes.
>
> Not being able to catch ARITH and all subclasses like a "ARITH MATRIX"
> with the same clause - just because the latter has list-meta-syntax that
> needs to be taken care of - feels just wrong to me.
What are you talking about? Apart from the fact that [list "ARITH
MATRIX" foo bar] isn't generating an ARITH code in the first place,
which is a bug in the *example*.
> If we specified the pattern to be applied only to [lindex $errorCode 0]
> or [join $errorCode], that would also solve the problem.
No it wouldn't. The first option would mean that in practical cases you
would only be able to trap POSIX or ARITH, not a subtype. The second
would mess up later words in the errorCode which *can* conventionally
contain spaces.
Subtype descriptors are separate words, as you would know if you'd ever
actually looked at them! Here's a couple of real examples:
$ tclsh8.5
% open nosuchfile
couldn't open "nosuchfile": no such file or directory
% set errorCode
POSIX ENOENT {no such file or directory}
$ tclsh8.6
% info nosuchopt
unknown or ambiguous subcommand "nosuchopt": must be [...]
% set errorCode
TCL LOOKUP SUBCOMMAND nosuchopt
(OK, I shortened the error message line...)
> Otherwise we'd have to discourage use of spaces and all other
> list-special characters in user defined errorcodes.
You're wrong. You're erecting a whole baroque architecture to deal with
something that just *is not a problem*. That's a good way to get no
respect at all from me...
Donal.
|
|
From: Twylite <tw...@cr...> - 2008-11-23 17:45:00
|
Hi,
> 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.
>
I take it from your proposal for "as {msgvar optsvar}" that this isn't
considered "nested parsing of lists"?
> Out Of Scope! If someone needs something that complicated, they'll have
> to write their own code.
>
Having to write your own control structure just because the existing one
doesn't do what you need (or at least doesn't do it in a pretty way) is
what this exercise is all about, and what we're trying to avoid
happening again.
> 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!
>
Oh dear ... I was building a Jeep.
> 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...)
>
It occurs to one that once upon a time there was a need for a simpler,
prettier alternative to
if/then/elseif/elseif/elseif/elseif/elseif/else. And so [switch] was
born. It also occurs to me that in C a switch is over a set of integer
values. In Tcl it was obvious to make [switch] operate on strings, but
not just that - it would be able to match against wildcard patterns _and
regular expressions_. And to do so it would add interface complexity
and sacrifice performance (in particular it was necessary to specify the
order of evaluation).
Are you _sure_ glob is enough? I'm not. So I want a syntax that
doesn't preclude extension (in a pretty) to handle other options in the
future. And I'd like a syntax that allows developers to create these
extensions outside the core, so that these options can evolve in future
rather than end up in a length discussion that really has few facts and
figures to back up things like "most developers" and "common case".
> 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
>
Versus:
on code ?-howtomatch whattomatch? script
I cannot comment on the implications of byte-coding that, but I do feel
that it is more consistent (on error vs trap), more flexible, etc.
Your proposal is of course extensible by adding new handler keywords in
future (assuming the TIP proposers at the time can agree on the
keyword), but this would have to be done in the core.
Regards,
Twylite
|
|
From: Andreas L. <av...@lo...> - 2008-11-23 17:31:32
|
"Donal K. Fellows" <don...@ma...> wrote:
> Twylite wrote:
> > I believe the point was:
> > % string match ARITH* [list "ARITH MATRIX" foo bar]
> > 0
Yes, that's what I meant.
> But since we don't construct error codes like that, it doesn't matter.
> If someone does, they can use:
> string match {{ARITH MATRIX}*} ...
Perhaps it's just me that I envision hierachies of error classes.
Not being able to catch ARITH and all subclasses like a "ARITH MATRIX"
with the same clause - just because the latter has list-meta-syntax that
needs to be taken care of - feels just wrong to me.
If we specified the pattern to be applied only to [lindex $errorCode 0]
or [join $errorCode], that would also solve the problem.
Otherwise we'd have to discourage use of spaces and all other
list-special characters in user defined errorcodes.
|
|
From: Donal K. F. <don...@ma...> - 2008-11-23 17:20:39
|
Joe English wrote: > (I'm also somewhat alarmed at the growing complexity > of the error matching facilities -- especially because > I am not yet convinced that they will be useful in practice. > I'd rather start with something braindead simple and > add to it later. Features are easy to add, but > incompletely baked features are very very hard to > get rid of.) I agree. At least some of the things floating round are enough over what seems sensible and practical that they'll attract a NO vote from me if formally proposed. Donal. |
|
From: <lm...@bi...> - 2008-11-23 17:12:49
|
On Sun, Nov 23, 2008 at 09:02:05AM -0800, Joe English wrote: > (I'm also somewhat alarmed at the growing complexity > of the error matching facilities -- especially because > I am not yet convinced that they will be useful in practice. > I'd rather start with something braindead simple and > add to it later. Features are easy to add, but > incompletely baked features are very very hard to > get rid of.) Amen. -- --- Larry McVoy lm at bitmover.com http://www.bitkeeper.com |
|
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 |
|
From: Twylite <tw...@cr...> - 2008-11-23 17:03:22
|
Hi,
>> Concerns:
>> - How to handle "all other errors" (-like * would work, is that good
>> enough?)
>> - No handlerscript may begin with a "-".
> Which conflicts with the specification that "-" as a handlerscript
> means fall-through to next branch.
No, just poor clarity on my part. If the element under consideration is
a "-" then it is a handlerscript (body) with the special meaning "fall
through". Otherwise if the element begins with "-" then it indicates a
matcher, and the following elements will be an errorPattern and a
handlerscript (body).
>> Alternatives:
>> - The body "-" is reserved to indicate fallthrough to the next body.
>> The body "+" could be reserved to indicate that a matcher and pattern
>> follow.
>> e.g.
>> on error + like "POSIX *" { ... }
> I don't understand how this + syntax differs from the -like "POSIX *"
> syntax.
Instead of reserving all handlerscripts starting with "-" (they will be
treated as matchers), there will be exactly two reserved handlerscripts:
"-" means falls through, and "+" meaning "this is not a body, the
following three elements are matcher, errorPattern and body".
> Overall, I think the proposal ends up with [try] doing too much. In
> particular, it seems doomed to a linear trawl through various match
> conditions. Specifying an overall match command and then passing it
> all the patterns and handler scripts at once gives much more freedom
> for efficient implementation.
And that freedom makes the behaviour of the command uncertain from the
users perspective. Will each matcher consider the relevant handlers in
left-to-right order? Will each matcher execute the handler body in a
consistent manner?
Bear in mind that this linear trawl only takes place when there are
multiple handlers for the same return code -- matching exceptions
(return code) is efficient.
> I take your point though that the pattern matching scheme is dictated
> by whoever produced the error more than whoever is catching it. My,
> this gets complicated. Frankly, I'd rather let one or more
> implementations sit in tcllib or elsewhere for a bit until it becomes
> clear what the best approach is. I.e., I believe experience in use is
> going to be crucial here, rather than trying to design from
> principles. I'd be surprised if we can settle a design in time for 8.6.
Unfortunately even in tcllib we aren't going to get much experience with
this. None of the other [try] extensions out there have received
widespread adoption.
Regards,
Twylite
|
|
From: Joe E. <jen...@fl...> - 2008-11-23 17:02:28
|
Twylite wrote:
[ extensive summary - thanks, that was helpful! ]
Just one comment for now:
> 2. Look & Feel
> (d) Capture of variables (return code, result and options dict) needs to
> happen at the front of the [try] for the statement as a whole, rather
> than per handler. This avoids confusion over which vars will be defined
> after the [try] returns, and also avoids variable churn if the
> errorPattern to be matched can access the variables. Although some
> amount of locality is lost, this also makes the syntax cleaner (less
> repeated "noise").
I'm not sure about this.
try {
open $filename w
} as {code var} on ok {
# (1)
} on error {
# (2)
}
In block (1), $var holds an open file handle;
in block (2) it holds an error message.
Personally I'd prefer having different variable names
in the different branches:
try {
open $filename w
} on {ok fp} {
...
} on {error msg}
...
}
It also unconditionally binds the variable 'code',
which is unused and unneeded. (In blocks (1) and (2)
you already know what $code is; outside of the [try]
command you no longer care.)
(I'm also somewhat alarmed at the growing complexity
of the error matching facilities -- especially because
I am not yet convinced that they will be useful in practice.
I'd rather start with something braindead simple and
add to it later. Features are easy to add, but
incompletely baked features are very very hard to
get rid of.)
--Joe English
jen...@fl...
|
|
From: Magentus <mag...@gm...> - 2008-11-23 16:53:56
|
On Sun, 23 Nov 2008 14:45:17 +0200,
Twylite <tw...@cr...> wrote:
> (g) Discourage the use of the result for determining the nature of
> the error (an in doing so encourage the use of -errorCode). At the
> very least this means not having default support for matching on the
> result.
Keeping in mind that the return result might be the NORMAL place to
match for SOME return codes. Namely OK and custom codes >4.
> (b) Handlers are identified by keywords. The keyword "catch" has
> been argued against (confusion with existing language
> feature/keyword), as has "except" (ambiguous - "with exception" or
> "except for"). Likely candidates are "on" and "handle".
I like "on" for the generic catch-a-return-code case, and "handle" as
in handle-the-error.
> (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.
Definitely per-handler. But source and test are different things;
message source will mostly be dependant on the return code, where any
of the basic types of string match test can be applied to every possible
message source. So unless you want every combination of source and
test explicitly spelt out in its own matcher, they need to be separate.
If a whole new error passing paradigm evolves, a new [try] token can be
built to work with it, which could be as simple as a new term which
takes a sub-set of the existing terms as its first argument, and
emulates those terms (I doubt the existing code will be particularly
reusable in that case anyhow).
> (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).
Would it make sense to "accumulate" finally bodies as you go through,
until you reach an active handler. This would mean there's a subtle
twist and a bit of surprise, in that the finally block should be right
behind the main [try] block, before any error handlers. Conversely,
run finally blocks only from a matching handler down. Does that make
any practical sense?
Also, would it make any sense to do it in the style of a C switch...
The handler body has to [break], otherwise it continues to try and
match. For example, on a write error, you might want to send an error
message and flush. Then if it's not a file closed error, send a
"connection closed" message, and flush. Finally you'll close the
connection if it's still open, if there was any kind of error at all.
This would set [try] apart from any other TCL control structure, giving
it a unique niche that even catch+switch can't readily support. Or
conversely, [continue] would cause it to keep looking, [break] would
prevent it from executing the finally block, and [return -code return]
could conceivably be used to alter the matching from here on down.
> Concerns:
> - How to handle "all other errors" (-like * would work, is that good
> enough?)
Personally I'd like an "else" clause... But "on *" would be good in
the presence of [continue] from above. And with basic glob matching,
"handle *" could short-circuit and not even bother doing the match.
Your present concept of the matcher is broken. It should not dictate
the source of the string being matched against, that's already done for
all normal usage cases, and the rest can be handled by [expr]-based
matching or almost certainly are better handled by an entirely
different structure.
> - No handlerscript may begin with a "-".
Sucky. My plan puts options only before the match string. If there's
no match string, then there's no options, either.
> - No feedback yet on "as {vars}" and the order of the vars
Sure you have. I suggested something like that earlier, except called
"catch". This is better.
> - If there are multiple handlers and one is unqualified, should it be
> executed first or last?
In the name of least surprise, execute it where it stands. That might
mask more specific ones further down, but it avoids magic.
Neil:
> 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.
It doesn't apply to [if] and most other control structures, and it only
applies to the [regexp] part of [switch], which is a very different
beast, as every single pattern has a different source of values for the
variables.
> 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.
That can be done regardless.
> 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).
It's been needed for a long time. Basic glob match for now, expand on
it once a decent mechanism is in place.
> I'd drop -llike -- too similar to -like, and the details of list
> matching are complex to do right with nested sub-lists. But that
> assumes all list elements are just strings (rather than e.g. being
> sub-lists themselves), so only partially addresses the issue.
In a general context, that would be a problem. But is it expected to
be a problem for errorcode? Sounds like the purpose of errorcode needs
revisiting, to figure out just what it is and isn't supposed to be,
because their seems to be some disagreement as to its complexity.
>> - No handlerscript may begin with a "-".
> Which conflicts with the specification that "-" as a handlerscript
> means fall-through to next branch.
Only if your handlerscript is a command called "-" which takes no
arguments.
> Overall, I think the proposal ends up with [try] doing too much. In
> particular, it seems doomed to a linear trawl through various match
> conditions. Specifying an overall match command and then passing it
> all the patterns and handler scripts at once gives much more freedom
> for efficient implementation.
I had the strange impression that a linear trawl through various match
conditions is exactly what we're doing. It can be made a little more
intelligent by grouping based on code, and adjacent matches using the
same match type can be grouped by a [try] bytecode compiler (as DKF
pointed out just as I was about to click Send).
DKF:
> 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
I hate to say it, but that's the basis of what I've been arguing for,
except that I added one extra handler type for OK (match on return
value for non-fatal failures), and the ability for code to have a
second word (again matched against the return value) for the regular
case of return codes >4.
--
Fredderic
Debian/unstable (LC#384816) on i686 2.6.23-z2 2007 (up 46 days, 10:07)
|
|
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.
|
|
From: Neil M. <ne...@Cs...> - 2008-11-23 15:59:57
|
On 23 Nov 2008, at 12:45, Twylite wrote:
> [...]
> 5. Proposal
>
> Based on this summary of the discussions so far, this is my current
> proposal:
>
> try tryscript ?as {vars}? ?handler ...? ?finally finalscript?
> where handler is
> on code ?-matcher pattern? handlerscript
> and
> handlerscript may be "-" to fall through to the next handlerscript
>
> The tryscript is executed and the outcome (return code, result,
> options
> dict) is captured into vars. A fast match (possibly a dict lookup) is
> performed to find the handler(s) for that code. If there is an
> unqualified handler (one with no matcher) or a single handler for the
> code, then it is executed; otherwise each handler is considered in
> turn
> (left-to-right order) by calling the associated matcher, and the first
> matching handler is executed. If no matching handler is found then
> the
> exception is propagated.
>
> 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
I'd drop -llike -- too similar to -like, and the details of list
matching are complex to do right with nested sub-lists. You could
just define it as:
proc llike {pattern list} {
foreach p $pattern item $list {
if {![string match $p $item]} { return 0 }
}
return 1
}
But that assumes all list elements are just strings (rather than e.g.
being sub-lists themselves), so only partially addresses the issue.
> - -expr for expr-based matching (with access to return code,
> result &
> options dict)
>
> Example of use:
>
> try {
> # do stuff
> } as {code em opts} on ok {
> # do more
> } on break - on continue {
> # special handing for break & continue
> } on error -like "POSIX *" {
> # handle POSIX errors
> } on error -expr { $em in {BAD FOO BAR} } {
> # support legacy errors
> } finally {
> # cleanup
> }
>
> Concerns:
> - How to handle "all other errors" (-like * would work, is that good
> enough?)
> - No handlerscript may begin with a "-".
Which conflicts with the specification that "-" as a handlerscript
means fall-through to next branch.
> - No feedback yet on "as {vars}" and the order of the vars
> - If there are multiple handlers and one is unqualified, should it be
> executed first or last?
>
> Alternatives:
> - The body "-" is reserved to indicate fallthrough to the next body.
> The body "+" could be reserved to indicate that a matcher and pattern
> follow.
> e.g.
> on error + like "POSIX *" { ... }
I don't understand how this + syntax differs from the -like "POSIX *"
syntax.
Overall, I think the proposal ends up with [try] doing too much. In
particular, it seems doomed to a linear trawl through various match
conditions. Specifying an overall match command and then passing it
all the patterns and handler scripts at once gives much more freedom
for efficient implementation.
I take your point though that the pattern matching scheme is dictated
by whoever produced the error more than whoever is catching it. My,
this gets complicated. Frankly, I'd rather let one or more
implementations sit in tcllib or elsewhere for a bit until it becomes
clear what the best approach is. I.e., I believe experience in use is
going to be crucial here, rather than trying to design from
principles. I'd be surprised if we can settle a design in time for 8.6.
-- Neil
This message has been checked for viruses but the contents of an attachment
may still contain software viruses, which could damage your computer system:
you are advised to perform your own checks. Email communications with the
University of Nottingham may be monitored as permitted by UK legislation.
|
|
From: Neil M. <ne...@Cs...> - 2008-11-23 15:43:07
|
On 23 Nov 2008, at 12:45, Twylite wrote:
> I think it's time for a summary of where we are on the try/catch/
> finally.
>
> The overall intent of the TIP can be summed up as "make a control
> structure that makes dealing with exceptions, errors and resource
> cleanup simpler - both logically and visually".
>
> 1. Functionality
>
> We want to
> (a) Handle return codes, so that we can build control structures and
> handle exceptions that use return codes. In most cases an exact match
> against a single integer (or magic name) is sufficient.
> (b) Handle matching against -errorCode in the case of the return code
> TCL_ERROR (1), so that we can have something similar to other
> languages
> with typed exception handling. In most cases a prefix match, or glob
> match, or element-wise glob match on a list is sufficient.
> (aside) Any argument about the ugliness of handling return codes with
> catch+if/then or catch+switch applies equally to handing errors &
> -errorCode, and vice versa. As a result this TIP must provide for
> both
> (a) and (b), although it is not necessarily a requirement that they
> are
> provided for in the same command.
> (c) Handle on those exceptions/errors that are of interest (can be
> handled at this point) and let others propagate normally.
> (d) Handle success continuation, i.e. branch when there is no
> error/exception. This is not generally supported by procedural
> languages but the requirement has been expressed by several developers
> and TCT members.
> (e) Handle cleanup at the end of a block of code by means of a
> "finally"
> handler (regardless of errors/exceptions).
> (f) Have reasonable performance, at least for the common cases.
> (g) Discourage the use of the result for determining the nature of the
> error (an in doing so encourage the use of -errorCode). At the very
> least this means not having default support for matching on the
> result.
> (h) For exceptions thrown from handlers and finally blocks,
> maintain the
> details of the original exception (i.e. chain exceptions in the
> options
> dict).
Agree with all of these.
>
> 2. Look & Feel
>
> (a) It's going to be called [try]
> (b) Handlers are identified by keywords. The keyword "catch" has been
> argued against (confusion with existing language feature/keyword), as
> has "except" (ambiguous - "with exception" or "except for"). Likely
> candidates are "on" and "handle".
> (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.
Agreed.
> (d) Capture of variables (return code, result and options dict)
> needs to
> happen at the front of the [try] for the statement as a whole, rather
> than per handler. This avoids confusion over which vars will be
> defined
> after the [try] returns, and also avoids variable churn if the
> errorPattern to be matched can access the variables. Although some
> amount of locality is lost, this also makes the syntax cleaner (less
> repeated "noise").
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.
> (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.
>
> 3. Matching
>
> (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.
> (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).
> (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.
> (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).
> (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.
> (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'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.
>
> 4. General
>
> These are weakly-expressed requirements or requirements of my own.
>
> (a) There is a general desire for consistency / symmetry in the
> syntax.
> This would obviously improve the readability & understandability of
> the
> source code.
> (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:
upvar 1 $msgVar msg $optsVar opts
set rc [catch { $script } msg opts]
invoke 1 $matchcmd [dict get $opts -errorcode] [dict get $handlers
$rc]
should do the right thing for most matching constructs.
I also believe the order in which to consider patterns should be left
to the match command.
[... snip proposal: I'll post a separate message for that ...]
-- Neil
This message has been checked for viruses but the contents of an attachment
may still contain software viruses, which could damage your computer system:
you are advised to perform your own checks. Email communications with the
University of Nottingham may be monitored as permitted by UK legislation.
|
|
From: Donal K. F. <don...@ma...> - 2008-11-23 15:26:25
|
Twylite wrote:
> I believe the point was:
> % string match ARITH* [list "ARITH MATRIX" foo bar]
> 0
But since we don't construct error codes like that, it doesn't matter.
If someone does, they can use:
string match {{ARITH MATRIX}*} ...
Donal.
|
|
From: Joe E. <jen...@fl...> - 2008-11-23 14:53:36
|
Jan Nijtmans wrote:
> This is a Call For Votes on TIP #340.
>
> TIP #340: CONST Qualification of Tcl_SetResult's argument and -Wwrite-string
TIP#340: NO.
I support the goals of this TIP, but not the specific
proposed refactoring. It leaves Tcl_SetResult() in a
broken state: with an incorrect const qualifier on the
second argument and a worthless vestigial third argument.
What is called for is a new, two-argument, const-correct
entry point:
void Tcl_SetResultString(Tcl_Interp *, const char *);
and for Tcl_SetResult() to be deprecated in its entirety.
(Or not. Keeping it around is cheap.)
--Joe English
jen...@fl...
|
|
From: Magentus <mag...@gm...> - 2008-11-23 13:29:27
|
On Sat, 22 Nov 2008 14:06:59 +0000,
Neil Madden <ne...@Cs...> wrote:
>> Supporting all the different types of match, though, would be a
>> "Good Thing". -glob, -nocase, -exact, -prefix, -regexp, and so
>> forth... That's why I think the next part is worth giving a second
>> thought.
> If these are supported it should be only by explicit delegation to
> [switch], rather than making all these options part of the interface
> of [try] too.
I've had the impression for a while now that TCL needs a generic
extensible matching framework that can be plugged into any command.
Not gonna make it into 8.6, but might be worth considering for the
future of not only [try] but the rest of TCL also. My thoughts have so
far run something like this;
Start with a Tcl_Parse_Match_Options() building a struct that can be
passed to a matching Tcl_Perform_String_Match() function to match two
strings with previously specified options. TPMO() would accept any
option not already recognised (or vice-versa), and if it's one of its
options, consume it and add it into the current matching options struct
(allowing the options to be inter-mixed with those of the surrounding
command).
To alleviate the problem of option bloat, a good deal of them could
perhaps be eventually phased out in deference to a single -match option
(-glob, -exact, -prefix, -regexp, etc.), allowing new match functions
to be added to a ::tcl::match namespace, and picked up automatically by
every command using the matching framework. The modifiers (such as
-nocase) would become options to the -match options value.
eg. -match {glob -nocase}
The commands in ::tcl::match would ALL support extraction of the
matched regions, ala [regexp]. But they would ONLY support the -index
method (for efficiency), returning the start and stop of each matched
section. The enclosing command (or a secondary helper) would be
responsible for extracting the actual corresponding strings.
A second-layer matching framework could well extend it a step further
to also pick up on the grouping options, index options, and similar,
reducing [lsearch] to nothing but a very simple wrapper, and allowing
an [lmatch] command that walks two lists, instead of one list and a
static value, in the same manor.
Further, the -match method could be "complex", indicating that the match
arguments are themselves distinct -match values (which in turn may be
nested "complex" descriptions), allowing it to handle deep matching of
any repeated regular nested list structure.
Finally, the original TPMO() function (and the complex match method)
can look at the match it's being asked to use, and if it's one of the
built-in matches, obtain the core match function to be invoked
directly. For other non-built-in matches, it'd invoke a wrapper that
in turn invokes the specified TCL command, though with as much of
the pre-invocation setup as possible already performed to hopefully
alleviate some of the -matchcommand slow-down.
--
Fredderic
Debian/unstable (LC#384816) on i686 2.6.23-z2 2007 (up 46 days, 7:13)
|