|
From: Neil M. <ne...@Cs...> - 2008-11-23 11:44:13
|
Andreas Leitgeb wrote:
> On Sun, Nov 23, 2008 at 01:16:15AM +0000, Neil Madden wrote:
>> I believe I proposed a "--" didn't I?
> I just meant that the "--" should even then be kept, if all other
> options were deferred for later (if at all)
>
>>> [ {POSIX *} ] somehow does strike me as odd, [...as...], we
>>> are *supposed* to use a string operation (pattern-matching)
>>> on a list ($errorCode).
>>> Perhaps this pattern should be itself taken as a list, and then
>>> glob-matched element-wise (to the length of the pattern).
>> This is exactly the purpose of -matchcommand.
>
> But my point was, that a list-aware matching should happen by
> default, such that most of the cases it works correctly, even
> without implementing and installing a custom matcher.
>
> If usage of errorCode catches on (as a hoped-for result of the
> new try-command), then sooner or later someone will define
> sub-types like "ARITH MATRIX" and wonder, why ARITH* doesn't
> match both ARITH and "ARITH MATRIX".
> It of course doesn't match the latter, because that actually
> looks like "{ARITH MATRIX} ..." thus would need an optional
> open brace be matched as well (How to do that with globs?)
> And then it may even look like "ARITH\ MATRIX ..." sometimes,
> namely if some later element of the errorCode happens to
> contain an unpaired brace.
% string match ARITH* [list ARITH MATRIX]
1
% string match ARITH* [list ARITH MATRIX \{]
1
% string match ARITH* [list ARITH MATRIX \}]
1
% string match ARITH* {ARITH MATRIX \}}
1
It works fine. It would fail on [list [list ARITH MATRIX]]. The only
problem is that it is only capable of recognising very simple regular
languages, whereas list syntax is context-free so you can't match parts
of nested sublists very easily (or at all). Twylite has convinced me
that glob matching is sufficient for 80+% of basic cases for [try].
There is no general list-pattern syntax in Tcl at the moment, so doing
something more would require a much expanded scope for the TIP. List
pattern matching is much more tricky due to the requirement to know what
the expected types of elements are (so you can reliably distinguish
sub-lists from strings and so on).
[...]
> Introducing a list-string mixup directly in the core
> is a very bad move, imho.
I think it's fine in this case. No errors can arise because of it. We
are not constructing or extracting lists here, just a simple match. We
don't have to worry about balanced braces or quoting issues.
-- 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 12:47:22
|
Hi,
> % string match ARITH* [list ARITH MATRIX]
> 1
> % string match ARITH* [list ARITH MATRIX \{]
> 1
> % string match ARITH* [list ARITH MATRIX \}]
> 1
> % string match ARITH* {ARITH MATRIX \}}
> 1
>
I believe the point was:
% string match ARITH* [list "ARITH MATRIX" foo bar]
0
> of nested sublists very easily (or at all). Twylite has convinced me
> that glob matching is sufficient for 80+% of basic cases for [try].
>
Great :) But please don't take that to mean that I am convinced myself ;/
Twylite
|
|
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: 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: 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: 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: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: 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: Magentus <mag...@gm...> - 2008-11-25 05:13:56
Attachments:
signature.asc
|
On Sun, 23 Nov 2008 17:47:25 +0000, "Donal K. Fellows" <don...@ma...> wrote: > Subtype descriptors are separate words, as you would know if you'd > ever actually looked at them! Here's a couple of real examples: Could you, then, post right here a formal specification (or link to same on the tcl.tk site) of what the errorcode looks like, just as a marker point to set this part of the discussion straight. For example; Is the value a guaranteed list? Will it ever be a nested list? Are the text sections (those that may include spaces) guaranteed to be quoted to preserve the list beneath? Will they (text sections) always only be the last word(s) of the errorcode list? Is there anything else to act as an indicator to separate error hierarchy from arguments/text that may be useful to an errorcode parser? I think without a formal description of what errorcodes actually are, this sub-thread has been chasing its own tail just a little. -- Fredderic Debian/unstable (LC#384816) on i686 2.6.23-z2 2007 (up 47 days, 23:23) |
|
From: Donal K. F. <don...@ma...> - 2008-11-25 09:16:17
|
Magentus wrote: > Could you, then, post right here a formal specification (or link to > same on the tcl.tk site) of what the errorcode looks like, just as a > marker point to set this part of the discussion straight. No, it was never thought necessary. But I can point out that the function at the C level that builds the errorcode builds a list from its arguments, and has been documented to do so since... well, it's documented in the Ousterhout book, so that makes it at least 15 years old. While strictly you can build it yourself directly, nobody does. See the 'tclvars' manual page for what formal information we have, and 'Tcl_SetErrorCode' for the constructor function. > I think without a formal description of what errorcodes actually are, > this sub-thread has been chasing its own tail just a little. Yes, and you've been one of the main sources of misinformation. Donal. |
|
From: Joe E. <jen...@fl...> - 2008-11-25 18:13:15
|
Magentus asked: > Donal K. Fellows wrote: > > Subtype descriptors are separate words, as you would know if you'd > > ever actually looked at them! Here's a couple of real examples: > > Could you, then, post right here a formal specification (or link to > same on the tcl.tk site) of what the errorcode looks like, just as a > marker point to set this part of the discussion straight. See return(3tcl), section "RETURN OPTIONS", subsection "-errorcode". See also tclvars(3tcl), section 'errorCode'. See also error(3tcl), section "DESCRIPTION", last paragraph. Or grep the source code. > I think without a formal description of what errorcodes actually are, > this sub-thread has been chasing its own tail just a little. Yes. If the participants in the thread better understood the nature of the problem to be solved we could maybe get some focus here. --JE |
|
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: 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: 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 21:15:19
|
"Donal K. Fellows" <don...@ma...> wrote:
> [about Andreas's suggestion of list-pattern ]
> It's also massively more complicated to implement and document.
complicated to document?
The <patList> is a list of glob-patterns applied each on
the positionally corresponding element of <errorCode>.
complicated to implement?
proc matches {patList errorCode} {
set i 0
foreach p $patList {
set errElem [lindex $errorCode $i]; incr i
if {![string match $p $errElem]} {return 0}
}
return 1
}
Ok, it's more than a single [string match], but it's not
massively more complicated.
> > Even if it is not considered for 8.6b1, I do hope it will
> > be in for 8.6.
actually I meant: string map {considered implemented}
|
|
From: Andreas L. <av...@lo...> - 2008-11-25 10:02:40
|
Fredderic <mag...@gm...> wrote: > "Donal K. Fellows" <don...@ma...> wrote: > > Subtype descriptors are separate words, as you would know if you'd > > ever actually looked at them! Here's a couple of real examples: > > Could you, then, post right here a formal specification (or link to > same on the tcl.tk site) of what the errorcode looks like, just as a > marker point to set this part of the discussion straight. It's in the tclvars man page (and surely also in the html-pendants) It is a list, the first element of which gives the type, and thereby determines the interpretation of the rest. For those types thrown by the core these interpretations are also given (ARITH,POSIX,...). With all the changes in progress, and the global variable errorCode practically vanishing, it may be necessary to move it's explanation to "error", "catch", "throw" and/or "try" docs. |
|
From: Andreas L. <av...@lo...> - 2008-11-25 11:49:26
|
"Donal K. Fellows" <don...@ma...> wrote: > But tackling the more complex cases with code inside the handler blocks > is exactly the right thing. One point of "try" and it's error-filtering is to make all unhandled exceptions fall through, run the finally block and then get rethrown. What would be the standard idiom with "switch inside a handler body", to get this behaviour from the switch's default block? PS: Is it really that hard to call non-inlined matcher-commands from generated bytecode? PPS: I do also feel addressed by "astronomer", and I don't feel insulted by this classification in this context. |
|
From: Donal K. F. <don...@ma...> - 2008-11-25 12:58:04
|
Andreas Leitgeb wrote:
> One point of "try" and it's error-filtering is to make all unhandled
> exceptions fall through, run the finally block and then get rethrown.
The 'finally' block gets run in all (trappable) cases.
> What would be the standard idiom with "switch inside a handler body",
> to get this behaviour from the switch's default block?
You use [return] with right options to rethrow an exception, but you
also only trap the stuff that is appropriate in the first place. None of
which has anything to do with 'finally' processing.
The way in which [try] works has got to be this:
set code [catch $firstbody $msgVar $optVar]
set handler [pick handler based on $code [set $msgVar] [set $optVar]]
set code2 [catch $handler msg2 opt2]
eval $finallybody
if {$code2 != 0} {
set code $code2; set $msgVar $msg2; set $optVar $opt2
}
return -code $code -options [set $optVar] [set $msgVar]
Or something like that. I've spent as long on that as it took to type.
All that is missing is the code to actually pick the handler script,
which in turn should be kept simple as well.
> PS: Is it really that hard to call non-inlined matcher-commands from
> generated bytecode?
It's even more trivial to compile a script. Guess what? You can just put
that stuff in the script in the first place. So why do we need a
generalized matcher architecture? Answer: We don't. So why are you
developing one? (That's the part I find hard...)
> PPS: I do also feel addressed by "astronomer", and I don't feel
> insulted by this classification in this context.
Not "astronomer", "astronaut". With reference to
http://www.joelonsoftware.com/articles/fog0000000018.html
Donal.
|
|
From: Donal K. F. <don...@ma...> - 2008-11-25 13:16:15
|
Donal K. Fellows wrote: > Not "astronomer", "astronaut". With reference to > http://www.joelonsoftware.com/articles/fog0000000018.html And also: http://www.acmqueue.org/modules.php?pa=showpage&pid=505&name=Content I hold architecture astronautics in contempt. Reminds me too much of work and of how projects can go wrong for failing to focus on critical details. Donal. |
|
From: Magentus <mag...@gm...> - 2008-11-26 12:58:37
Attachments:
signature.asc
|
On Tue, 25 Nov 2008 17:56:54 +0200, Twylite <tw...@cr...> wrote: > Sadly it will be some time before I can gain value from this function > myself. Not until the third-party libraries I am tied to - which > require me to parse the (non-localised) result - are updated to > produce an errorcode. Not until I find enough time on or between > projects to refactor legacy code (core libraries that I depend on and > use in pretty much all new utilities and applications) to use > errorcode rather than (or, for backwards compatibility, in addition > to) a list structure in the result. Not in places where I need to > maintain code that allocates & frees more than 2 resources, which can > be done cleanly using finally callbacks, but otherwise sends you to > the depths of nested try/finally blocks and you can't see the wood for > the error-and-cleanup-handling trees. THIS is the part I've been trying to deal with. - Support for all current return values, not just one limited view of reality, so that it's useful NOW, not some time in an unknown future that may or may not happen. (That's what happened to errorcode, it was created before the mechanisms existed to make good use of it, and it's floundered in obscurity ever since.) - And for cleaning up those messes of switch and other statements presently needed to support all kinds of error and result handling. If done right, it'll be fast and efficient for the simple case. And a heck of a lot easier to read and work with in the complex case. Especially when it's so damn simple trivial to do so much better. -- Fredderic Debian/unstable (LC#384816) on i686 2.6.23-z2 2007 (up 49 days, 6:43) |
|
From: Colin M. <co...@ch...> - 2008-11-26 13:45:54
|
Magentus wrote: > - And for cleaning up those messes of switch and other statements > presently needed to support all kinds of error and result handling. > If done right, it'll be fast and efficient for the simple case. And > a heck of a lot easier to read and work with in the complex case. > > Especially when it's so damn simple trivial to do so much better. > I don't see 'trivial', and I don't see 'better', in what's been proposed here at various times. I presume you're talking about [switch] being messy when it's used to decode error conditions. I see nothing messy about [switch]ing on conditions to discriminate different cases of error and take appropriate actions. Error conditions aren't somehow special, they're just more data to be processed, and if [switch] isn't an appropriate way to represent discrimination between cases, then that's a problem with [switch] which should be analysed. I see no problem with [switch], and I've seen no reports of any discomfort with [switch] in the role of case discriminator. The proposals I've seen would not be 'easier to read or work with', they obfuscate the processing required to properly handle errors by wrapping it in a gigantic command with so many options and internal argument syntax it may as well be another language. I can't name another such complex command in tcl core. About the only valid complaint I've seen about [catch] which doesn't rely upon the questionable premise of error data being somehow privileged is that it requires the use of temporary variables. I think this would be handled by a variant of [catch] which returned a dict whose values could then feed a [switch]. You can use string concatenation to test for error code, combine that with whatever you want to handle the error data returned in dict form. Arguments that error processing is complex and that it therefore requires a special kind of processing are specious. Any argument you can make that an error dict requires special processing should properly apply to absolutely any dict - the fact that the dict happened to be derived from an exception is immaterial. If someone made an argument that there needs to be a special tcl core command to handle (for example) processing a database record qua dict because 'handling database records is hard, and there's some messy code out there to do it' I doubt it'd even get to TIP. Colin. |
|
From: Andreas L. <av...@lo...> - 2008-11-25 17:13:44
|
On Tue, Nov 25, 2008 at 12:57:57PM +0000, Donal K. Fellows wrote:
> Andreas Leitgeb wrote:
> >One point of "try" and it's error-filtering is to make all unhandled
> >exceptions fall through, run the finally block and then get rethrown.
> The way in which [try] works has got to be this:
> set code [catch $firstbody $msgVar $optVar]
> set handler [pick handler based on $code [set $msgVar] [set $optVar]]
> set code2 [catch $handler msg2 opt2]
> eval $finallybody
> if {$code2 != 0} {
> set code $code2; set $msgVar $msg2; set $optVar $opt2
> }
> return -code $code -options [set $optVar] [set $msgVar]
Ok, that mutes some doubt I had. Anyway, nested switches would need
to explicitly re-throw errors not handled. Not a big issue, but it
shrinks the advantage of [try] against old [catch {...}].
> All that is missing is the code to actually pick the handler script,
> which in turn should be kept simple as well.
> >PS: Is it really that hard to call non-inlined matcher-commands from
> > generated bytecode?
>
> It's even more trivial to compile a script. Guess what? You can just put
> that stuff in the script in the first place.
Well, you said, that bytecoding a more advanced matcher/picker would be
exorbitantly more complex, so I wondered if calling out to a separate
command to do the picking wouldn't help to prevent that exponential
explosion of effort bytecoding a saner check.
> So why do we need a generalized matcher architecture?
> Answer: We don't. So why are you developing one?
Here is a little difference between me and Fredderic.
I do not primarily envision all those pluggable handlers, but
I'm very unhappy with using glob-matching on lists(*). Since I do
not see any chance to stop that particular train heading wrong
direction, I do hope for some spare rails that would at least
allow the next train (8.7 or so) to go in a better direction,
while not derailing this current train on its trip.
*:
I really thought the paradigm was to *reduce* the number of
places where lists are stringified...
If you think, that embedding switches is a good idiom, then
why not just match the [lindex $errorCode 0] with a glob or
even exactly, and leave further matching to embedded switches?
Still better than globbing a list, imho.
> Not "astronomer", "astronaut". With reference to
> http://www.joelonsoftware.com/articles/fog0000000018.html
Ok, this definition doesn't suit me that well. I may lose
ground with some visions, but hardly ever for high abstractions.
|
|
From: Twylite <tw...@cr...> - 2008-11-25 17:44:57
|
Hi, > If you think, that embedding switches is a good idiom, then > why not just match the [lindex $errorCode 0] with a glob or > even exactly, and leave further matching to embedded switches? > Still better than globbing a list, imho. > Because that's so unspecific as to be worthless in most cases. This would allow you to distinguish between (say) POSIX errors and ARITH errors, but in most cases where you need to branch based on the type of error you are distinguishing between two very similar errors (an IO timeout error versus an IO read error, a connect error versus a read error versus an authentication error, etc.). In addition any third-party package that wants to avoid naming conflicts is probably going to use the package name (or company name, or some other distinguished identifier) as the most general class of exception, which would make matching on [lindex $errorCode 0] virtually useless. Regards, Twylite |
|
From: Andreas L. <av...@lo...> - 2008-11-25 18:26:25
|
On Tue, Nov 25, 2008 at 07:44:32PM +0200, Twylite wrote:
> >If you think, that embedding switches is a good idiom, then
> >why not just match the [lindex $errorCode 0] ...
> Because that's so unspecific as to be worthless in most cases. This
> would allow you to distinguish between (say) POSIX errors and ARITH
> errors, but in most cases where you need to branch based on the type of
> error you are distinguishing between two very similar errors (an IO
> timeout error versus an IO read error, ...
Ok. Agreed. That is common enough to justify an idiom
more concise than a nested switch.
Even {CHILDKILLED * SIGSEGV *} may have its use. The errorCodes
thrown from core appear to have been carefully crafted to be
reasonably glob-able. At this point in time, glob appears like
the perfect hammer for the nail, but nails are likely going to
change when programmers get more into the habit of creating new
errorCodes for their applications, and introducing ambiguities,
that could have been avoided by list patterns in the first place.
|
|
From: Joe E. <jen...@fl...> - 2008-11-25 19:39:45
|
Donal K. Fellows wrote:
> The way in which [try] works has got to be this:
>
> set code [catch $firstbody $msgVar $optVar]
> set handler [pick handler based on $code [set $msgVar] [set $optVar]]
> set code2 [catch $handler msg2 opt2]
> eval $finallybody
> if {$code2 != 0} { <== this isn't right
> ^^^^^^^^^^^^^^^^^^
> set code $code2; set $msgVar $msg2; set $optVar $opt2
> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> # This part (^^^) should be unconditional
> }
> return -code $code -options [set $optVar] [set $msgVar]
>
> Or something like that. I've spent as long on that as it took to type.
The result of [try] should be the result of the handler clause,
regardless of whether it succeeds or not.
It should be:
set code [catch $mainScript value opts]
if {some clause '{XXX resultVar optsVar} handlerScript' matches} {
set $resultVar $value ; set $optsVar $opts
set code [catch $handlerScript value opts]
}
eval $finallyScript ;# exceptions propagate
# here: $finallyScript yielded TCL_OK
return -code $code -options $opts $value
--Joe English
jen...@fl...
|