Twylite wrote:
> >> > TIP #329 Try/Catch/Finally syntax
> > I'd really like to see this in 8.6. However, I also think
> > it's essential that try/catch be able to dispatch based on
> > the return code, not just $::errorCode, which the current
> > specification does not provide for. Please fix!
> >
> Although I haven't updated the spec, the current proposal is:
> try {
> #code
> } then {
> #success continuation
> } onerror {glob emvar optsvar} {
> #handle errors based on errorCode
> } except {spec emvar optsvar} {
> #handle errors based on any matching information in optsvar
> } finally {
> #always execute this as the last action before leaving the try command
> }
>
> The "except" clause will handle exceptions (non-zero Tcl return code) as
> opposed to errors (Tcl return code TCL_ERROR with dispatch based on
> errorCode). Not certain on what the "spec" in the except clause is
> going to look like though. Suggestions welcome (via e-mail or to
> http://wiki.tcl.tk/21608).
I would suggest:
try {
...
} onerror {pattern ?resultVar ?optionsVar??} {
#
# return code was TCL_ERROR, errorCode matches $pattern
#
} handle {code ?resultVar ?optionsVar??} {
#
# return code was $code.
#
} finally {
...
}
where "code" is one of ok/error/return/break/continue
or an integer literal, a la [return -code].
If a "then" clause is desired, then
try { # script... } then { # success continuation.. }
would be a synonym for
try { # script... } handle ok { # success continuation ... }
although I suspect a more common usage pattern would look like:
try {
open $filename "w"
} handle {ok fp} {
try {
# ... write to $fp
} finally {
close $fp
}
} onerror {{POSIX EACCESS *}} {
# ...
} handle {error msg} {
report "Unrecognized error: $msg"
}
> I still have concerns about this though:
> - The construct is getting pretty bulky - is it really adding power &
> simplicity as it is intended to do?
Yes. Dispatching based on the return code is essential
for creating user-defined control structures.
> [...]
> A modification I find particularly interesting is an alternative
> approach to finally. The current approach - while typical for try/catch
> syntax - is often a source of subtle bugs. It is common for a finally
> to have to check each resource before cleaning it up (and equally common
> for checks to be missed or assumptions made ... e.g. if { $somevar ne {}
> } { # cleanup } but an exception was thrown before somevar was set.
>
> A nested try/then/finally may go some way to address this situation, [...]
I believe so. Nested try/finally clauses -- one for each
resource that needs to be cleaned up -- all wrapped in
an outer try/catch for error recovery would cover
all the exception handling needs I can think of.
--Joe English
|