package require trycatch 2.0 namespace import trycatch::* try {...} try {...} catch ?-msg msgVar? ?-code codeVar? ?-info infoVar? {...} try {...} finally {...} throw code message onerr ?-code errorCode? pattern {...} pattern {...} ...
The trycatch package defines a general purpose exception-handling control structure on top of the standard "catch" command. The following commands are defined:
try {tryscript}
proc div {a b} { set quotient "NaN" try { set quotient [expr {$a/$b}] } return $quotient }This function will return the quotient of the two inputs, or "NaN" (Not a Number) if for any reason the computation failed.
Note that if the tryscript contains "return", "break", or "continue" commands, they will function as one would expect. For example, the above function could be rewritten as follows:
proc div {a b} { try { return [expr {$a/$b}] } return "NaN" }If there's no error computing the quotient, the computed value will be returned; but if there is, control will continue with the code following the "try", and "NaN" will be returned.
try {tryscript} catch ?options? {catchscript}
For example, the division example could be written as follows:
proc div {a b} { try { return [expr {$a/$b}] } catch -msg msg { puts "Warning: arithmetic error in 'div $a $b': $msg" return "NaN" } }
try {tryscript} finally {finallyscript}
The "try/finally" form is used when a particular action must be taken, no matter what else happens. For example, suppose a program opens a file and begins to write to it. If an error occurs, writing will end; but the file must be closed whether the file is written successfully or not. For example:
set f [open "foo.dat" w] try { # Write various things to the file } finally { close $f }If an error occurs while writing, the finally clause will be executed, and then the error will be propagated normally.
Similarly, if the tryscript contains "break", "continue", or "return" commands they will be handled as one would expect--but the finallyscript will be executed first.
If the finallyscript contains "break", "continue", or "return" commands, an error will be raised. Errors in the finallyscript will be propagated normally.
Although it can be very useful, few Tcl packages bother to include error codes when they raise errors. The "throw" command is intended to encourage this worthy practice by putting the code first and the message second. The code should be a valid Tcl list of one or more elements. A typical pattern might be for the first token to be the package name, and the second to be a code identifying the specific error. Thus, for example, if the "try" command detects a syntax error it might throw the following error:
throw {trycatch syntax} "syntax: try {...} ...."
proc div {a b} { try { return [expr {$a/$b}] } catch -msg msg { onerr {ARITH DIVZERO} { return "NaN" } * { error "div failed: $msg" } } }The onerr command works by trying to match patterns against the specified errorCode; if a pattern matches, the subsequent script is executed. The error code to match is the value of the -code option, if any, or the value of the global variable errorCode.
The error code is a Tcl list; each error pattern should be a Tcl list of glob-patterns (see the "string match" command for more on glob-patterns). The onerr command tries to match each glob-pattern with the corresponding token in the error code; if there is a mismatch, or if there are more glob-patterns than error code tokens, then onerr goes on to the next pattern.
It is usual to provide a default error handler, using the single glob pattern "*". This matches the first token of any error code, and therefore will match any error code which hasn't yet been matched.
trycatch
was written by William H. Duquette.Version 2.0 added the "try" and "try/finally" forms of the command, changed the syntax of the "catch" clause, and added the "throw" and "onerr" commands.
Copyright © 2001, by William H. Duquette. All rights reserved.