|
From: Twylite <tw...@cr...> - 2008-11-19 09:18:04
|
Hi,
>> > 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 still have concerns about this though:
- The construct is getting pretty bulky - is it really adding power &
simplicity as it is intended to do?
- The "except" clause needs to be flexible enough to handle the expected
common use cases, but not so flexible/complex that it's easier to just
use catch. There is little clarity on what the "common use cases" are.
- Often information about an error is implied in the result (as in
Tcl_SetResult) rather than an errorCode -- can except (or some other
clause) adequately handle this case?
I'm still investigating the syntax in other languages to what we can
cherrypick ;)
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, but
there are more interesting approaches, e.g. a "finally /script/" command
that can be placed anywhere in a block of code, and queues script for
execution at the end of the block of code. This approach is cleaner (no
"finally" clause adding bulk to the try/catch syntax), and resource
allocation and cleanup concerns can be located together in the source
code (locality is a good thing). Error/exception handling is also
simplified as each finally script runs independently (exception
information is chained) - so if part of your 'finally' fails, other
parts will still run without having explicit exception handling in a
'finally' clause.
Simple example of alternate finally syntax:
try {
set f [open "myfile.txt" r]
finally [list close $f] ;# or finally { close $f } since it executes
in the context of the block
# ...
}
Anyway ... there is still work to be done ;/
Regards,
Twylite
|