Extending "catch" syntax?

3 views
Skip to first unread message

Jean-Claude Wippler

unread,
Apr 17, 1999, 3:00:00 AM4/17/99
to
Often, I find myself writing the following code:

if {[catch {blah} errmsg]} {
... do something with $errmsg ...
}

Could the catch syntax be extended as follows, with the same semantics?

catch {blah} errmsg {
... do something with $errmsg ...
}

Which I'd then probably reformat as:

catch {
blah
} errmsg {
... do something with $errmsg ...
}

It's no big deal, I just find that it resembles another common case:

catch {
a-different-blah-where-failure-is-acceptable
}

-- Jean-Claude

Norman Richards

unread,
Apr 17, 1999, 3:00:00 AM4/17/99
to
On Sat, 17 Apr 1999 23:21:14 +0200, Jean-Claude Wippler <j...@equi4.com> wrote:
> Often, I find myself writing the following code:
>
> if {[catch {blah} errmsg]} {
> ... do something with $errmsg ...
> }
>
> Could the catch syntax be extended as follows, with the same semantics?
>
> catch {blah} errmsg {
> ... do something with $errmsg ...
> }

Yes, the catch syntax is terrible. Actually, I find myself mostly doing:

if {[catch {cmd} err]} {
foo
} else {
bar
}


What I did to make things nicer was to write a try function which works
something like this:

try result {
# do the command sequence
} error {
# do something to handle the error condition
} success {
# do something to handle the success condition
}

I also added in an always clause for code that should always execute
regardless of success or failure. But I have not yet decided whether
it is really useful or if it is just fluff. In any case, here is
what I wrote. If anyone has suggestions on how to make it better,
please let me know.

proc try {var cmd args} {
upvar $var resvar

set errcode [catch {uplevel 1 $cmd} resvar]
foreach {tag code} $args {
switch -- $tag {
error {
if {$errcode!=0} {
uplevel 1 $code
}
}
success {
if {$errcode==0} {
uplevel 1 $code
}
}
always {
uplevel 1 $code
}
default {
error "unknown try tag $tag, should be error, success or always"
}
}
}
}

___________________________________________________________________________
o...@cs.utexas.edu soli deo gloria

Juergen Schoenwaelder

unread,
Apr 19, 1999, 3:00:00 AM4/19/99
to
Jean-Claude Wippler <j...@equi4.com> wrote:

: Could the catch syntax be extended as follows, with the same semantics?

[...]

I think it would be nice to actually allow to match pattern, like in a
switch statement:

catch {cmd} msg {
*foo* {
# do something if the $msg matches *foo*
}
*bar* {
# do something if the $msg matches *bar*
}
finally {
# this is done everytime we catch an error
}
}

Such an extension would indeed simplify error handling and it is fully
backwards compatible. It basically allows to use the error message as
a way to identify exceptions. Yes, I would love to see something like
this in the core.
Juergen
--
Juergen Schoenwaelder sch...@ibr.cs.tu-bs.de http://www.cs.tu-bs.de/~schoenw
Technical University Braunschweig, Dept. Operating Systems & Computer Networks
Bueltenweg 74/75, 38106 Braunschweig, Germany. (Tel. +49 531 / 391 3289)

Frederic BONNET

unread,
Apr 19, 1999, 3:00:00 AM4/19/99
to
Hi Jean-Claude,

Jean-Claude Wippler wrote:
>
> Often, I find myself writing the following code:
>
> if {[catch {blah} errmsg]} {
> ... do something with $errmsg ...
> }
>

> Could the catch syntax be extended as follows, with the same semantics?
>

> catch {blah} errmsg {
> ... do something with $errmsg ...
> }
>

> Which I'd then probably reformat as:
>

> catch {
> blah
> } errmsg {
> ... do something with $errmsg ...
> }


I've written something similar, close to the Java exception syntax. It
is available as the TclExcept extension (script-only and
Tcl7.6-compatible):

http://www.multimania.com/fbonnet/Tcl/TclExcept/index.en.htm

(or in french:)
http://www.multimania.com/fbonnet/Tcl/TclExcept/index.htm

It looks like:

try {
# something catcheable
} catch {msg} {
MyException {
puts "MyException occured: \"$msg\""
}
default {
puts "Unknown exception occured: \"$msg\""
}
} finally {
# something that is always executed
}

There is a "throw" command:

throw MyException "error!"

TclExcept is build onto catch and error, so it is 2-way compatible:
exceptions are errors that can be caught by "catch", and errors are
"Error"-type exceptions that can be caught by "try - catch" blocks.

I have a version on my disk that can handle re-throwing and exception
hierarchies (ie define exception types and subtypes), but I have to find
some time to write a decent doc on the new features.

See you, Fred
--
Frédéric BONNET frederi...@ciril.fr
---------------------------------------------------------------
"Theory may inform, but Practice convinces"
George Bain

Don Porter

unread,
Apr 19, 1999, 3:00:00 AM4/19/99
to
Juergen Schoenwaelder <sch...@ibr.cs.tu-bs.de> wrote:
> Such an extension would indeed simplify error handling and it is fully
> backwards compatible. It basically allows to use the error message as
> a way to identify exceptions.

Isn't that what ::errorCode is for?

--
| Don Porter, D.Sc. Mathematical and Computational Sciences Division |
| donald...@nist.gov Information Technology Laboratory |
| http://math.nist.gov/mcsd/Staff/DPorter/ NIST |
|______________________________________________________________________|

we...@scriptics.com

unread,
Apr 19, 1999, 3:00:00 AM4/19/99
to
In article <7ffioe$soe$1...@clover.cam.nist.gov>,

d...@cam.nist.gov wrote:
> Juergen Schoenwaelder <sch...@ibr.cs.tu-bs.de> wrote:
> > Such an extension would indeed simplify error handling and it is fully
> > backwards compatible. It basically allows to use the error message as
> > a way to identify exceptions.
>
> Isn't that what ::errorCode is for?

Right, in general there is the return code (ok, error, return, break,
continue) as well as the errorCode variable and the error result string. I
had thought of doing something like your "try", but switching on errorCode
and the return code.

-- Brent Welch <we...@scriptics.com>
Scriptics: The Tcl Platform Company.
http://www.scriptics.com

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/ Search, Read, Discuss, or Start Your Own

Alexandre Ferrieux

unread,
Apr 21, 1999, 3:00:00 AM4/21/99
to
Jean-Claude Wippler wrote:
>
> Often, I find myself writing the following code:
>
> if {[catch {blah} errmsg]} {
> ... do something with $errmsg ...
> }
>
> Could the catch syntax be extended as follows, with the same semantics?
>
> catch {blah} errmsg {
> ... do something with $errmsg ...
> }

Are you arguing that it should be done in C rather than

proc ifcatch {code var ecode} {
upvar $var v
if {[catch {uplevel $code} v]} {uplevel $ecode}
}

for performance reasons ?

Note that along the same lines (and with not much more Tcl code) we can
have all the various try...except...anyway constructs. IMHO the beauty
of Tcl is to provide *none* of them as primitive (only a bare-bones
[catch]), and yet allow anybody to write his preferred ones, still using
them as first-class constructs. Okay, for,foreach,while,if are
counter-examples of this orthogonality principle, but for (again)
obvious performance reasons...

Hey, I know you know that - sorry for the braindump :)

-Alex

Jean-Claude Wippler

unread,
Apr 21, 1999, 3:00:00 AM4/21/99
to
Alex,

> > catch {blah} errmsg {
> > ... do something with $errmsg ...
> > }
>
> Are you arguing that it should be done in C rather than
>
> proc ifcatch {code var ecode} {
> upvar $var v
> if {[catch {uplevel $code} v]} {uplevel $ecode}
> }
>
> for performance reasons ?

No. I understand that everything is possible as is, as your code again
shows nicely, but I'm wondering what the guiding principle here is...

Is Tcl a bells-and-whistles tool, where most of the things one needs are
ready for use?

Or is it a collection of primitives, which is complete in the sense that
everything else can be built on top them?

A purist will prefer the latter (I don't mean that negatively at all),
whereas a solutions provider might want to have more stuff ready-made.

As an example which I find very similar: "foreach" once grew into a more
general mechanism with the addition of parallel loop variables / cycles.

Where does/should/will Tcl stand on this?

(Or maybe the question should be: do we want a "try" in the std lib?)

-- Jean-Claude

Alexandre Ferrieux

unread,
Apr 21, 1999, 3:00:00 AM4/21/99
to
Jean-Claude Wippler wrote:
>
> (Or maybe the question should be: do we want a "try" in the std lib?)

Okay now I see ! (Sorry)
And I completely agree with your view: all these try/catch variants
would definitely find a natural place in the Standard Tcl Library (too
bad STL is already used as an acronym:). But of course not in the
'kernel' (C code of the interp).

-Alex

Steve McAndrewSmith

unread,
Apr 21, 1999, 3:00:00 AM4/21/99
to
In article <371DDFA7...@equi4.com>,
Jean-Claude Wippler <j...@equi4.com> wrote:

> No. I understand that everything is possible as is, as your code again
> shows nicely, but I'm wondering what the guiding principle here is...

With my experience with Tcl, and Tk especially, it would seem the guiding
principle is to satisfy both crowds: default behavior (e.g. bindings) to build
stuff quickly (and with a standard look and feel), with the option to override
anything and everything down to the bare source, for the hackers/masocists.

For this particular example, the solution would seem to be to add a default
argument to catch, at the C level, so you could still use both constructs.
For example:

catch { expr } {
do something
}

... as well as ...

if { [catch { expr }] } {
do something
}


While this might violate the "primative" principle, it would make for more
efficient usage, while still allowing people to stretch the language in odd
ways. "foreach" is, indeed, a good example of this - a core command which
has a relatively limited usage ("for" would be the appropriate primative),
but is just too damn useful.

IM(NS)HO ...

mo

unread,
Apr 24, 1999, 3:00:00 AM4/24/99
to
Frederic BONNET wrote:
>
> Hi Jean-Claude,

>
> Jean-Claude Wippler wrote:
> >
> > Often, I find myself writing the following code:
> >
> > if {[catch {blah} errmsg]} {

> > ... do something with $errmsg ...
> > }
> >
> > Could the catch syntax be extended as follows, with the same semantics?
> >
> > catch {blah} errmsg {
> > ... do something with $errmsg ...
> > }
> >
> > Which I'd then probably reformat as:
> >
> > catch {
> > blah
> > } errmsg {
> > ... do something with $errmsg ...
> > }
>


The Tcl/Java package also has a command like this so that Tcl errors
and Java errors can be managed in one command.

java::try {
...
} catch {TclException e} {
...
} catch {NullPointerException e} {
...
} catch {Exception e} {
...
} finally {
...
}

The real issue is that Tcl needs a catch that can be based on
a type of error not just an error. If the catch command was
changed it seems like the error command should also be given
a type.

error ?TYPE? msg

like so.

error MYERR1 "you did something wrong"


later
Mo DeJong
dejong at cs.umn.edu

Don Porter

unread,
Apr 24, 1999, 3:00:00 AM4/24/99
to
In article <37224F7B...@spam.com>, mo <n...@spam.com> wrote:
> The real issue is that Tcl needs a catch that can be based on
> a type of error not just an error. If the catch command was
> changed it seems like the error command should also be given
> a type.
>
> error ?TYPE? msg
>
> like so.
>
> error MYERR1 "you did something wrong"

That's what the global variable errorCode is for. The [error]
command already provides a form for setting it:

error "you did something wrong" "" MYERR1

sets ::errorCode to the value MYERR1. When the result of a
[catch] command indicates an error, the value of ::errorCode can
be examined to determine the type of error that occurred and how
to respond.

Hmmm. The catch(n) man page was recently improved by adding
an example of usage. Perhaps the example should be expanded to
show the use of ::errorCode and ::errorInfo?

See error(n), return(n), and tclvars(n) for more information.

Frederic BONNET

unread,
Apr 27, 1999, 3:00:00 AM4/27/99
to
Hi Mo,

mo wrote:
> The real issue is that Tcl needs a catch that can be based on
> a type of error not just an error. If the catch command was
> changed it seems like the error command should also be given
> a type.
>
> error ?TYPE? msg
>
> like so.
>
> error MYERR1 "you did something wrong"

There is already such a feature built in error and return. Actually, I
use it in TclExcept to make it compatible with standard catch/error.
Thrown exceptions have EXCEPTION code, and regulare errors are seen as
Error exceptions. Have a look at the error ("code" argument) and return
("-errorcode" switch) man pages, and at the errorCode global variable.

However "catch" catches all errors whatever their type. TclExcept and
other exception handling packages allow error-type-based handling. This
is perfectly feasible using standard Tcl features. It would be nice if
such a package could be provided in Tcl's standard library.

Alexandre Ferrieux

unread,
May 3, 1999, 3:00:00 AM5/3/99
to
mo wrote:
>
> how do I catch based on the type? As far as I can tell
> there is no way to use the catch command like the
> try {} catch {} finally {} statement in Java. For example, how
> would I catch one type of error but not catch another type of
> error without doing something nasty like this.
>
> if {[catch script err]} {
> test for type 1
> test for type 2
> test for type 3
> rethrow if not one of the ones you wanted
> }

This is exactly what a Tcl implementation of try..catch.finally would
do. So what ? Are you complaining that it's not already in C ? I love
the orthogonality of Tcl, i.e. its habit of providing independent raw
primitives in C, leaving it to the programmer to add tons of syntactic
sugar if he sees fit.

-Alex

Juergen Schoenwaelder

unread,
May 3, 1999, 3:00:00 AM5/3/99
to
Alexandre Ferrieux <alexandre...@cnet.francetelecom.fr> wrote:

: This is exactly what a Tcl implementation of try..catch.finally would


: do. So what ? Are you complaining that it's not already in C ? I love
: the orthogonality of Tcl, i.e. its habit of providing independent raw
: primitives in C, leaving it to the programmer to add tons of syntactic
: sugar if he sees fit.

The point here is that exception handling is a very important thing for
every script that is used more than once. The fact that different ways
of doing exception handling show up in various extensions make it more
difficult than necessary to combine extensions etc.

I think that a proper exception handling mechanism should be part of the
Tcl core (whether that is implemented in C or Tcl does not really matter).

Alexandre Ferrieux

unread,
May 3, 1999, 3:00:00 AM5/3/99
to
Juergen Schoenwaelder wrote:
>
> Alexandre Ferrieux <alexandre...@cnet.francetelecom.fr> wrote:
>
> : This is exactly what a Tcl implementation of try..catch.finally would
> : do. So what ? Are you complaining that it's not already in C ? I love
> : the orthogonality of Tcl, i.e. its habit of providing independent raw
> : primitives in C, leaving it to the programmer to add tons of syntactic
> : sugar if he sees fit.
>
> The fact that different ways
> of doing exception handling show up in various extensions make it more
> difficult than necessary to combine extensions etc.

At the lowest level, there is just ONE way of doing exception handling,
which is the integer return value of C functions being TCL_ERROR.
Interestingly, it needs no special compiler support (unlike C++-like
exception handling) nor from the OS (unlike MS exception handling
utils), hence it is maximally portable. So whatever you do in your
extension, you have one single (recommended) way of reporting
exceptions/errors to the caller. Since this way is 'feature-complete'
(in the sense that it is a primitive sufficient to implement all the
try.. variants and others in pure Tcl), I fail to see a need for a 'new'
standard.

-Alex

Juergen Schoenwaelder

unread,
May 3, 1999, 3:00:00 AM5/3/99
to
Alexandre Ferrieux <alexandre...@cnet.francetelecom.fr> wrote:

: At the lowest level, there is just ONE way of doing exception handling,


: which is the integer return value of C functions being TCL_ERROR.
: Interestingly, it needs no special compiler support (unlike C++-like
: exception handling) nor from the OS (unlike MS exception handling
: utils), hence it is maximally portable. So whatever you do in your
: extension, you have one single (recommended) way of reporting
: exceptions/errors to the caller. Since this way is 'feature-complete'
: (in the sense that it is a primitive sufficient to implement all the
: try.. variants and others in pure Tcl), I fail to see a need for a 'new'
: standard.

There are lots of commands or command features in Tcl that are not really
needed since you can rebuild these features on top of other primitives.
I believe that the "leader among scripting languages" (quoted from
Scriptics Tcl8.1 announcement) should have a standard exception handling
mechanism. Many people simply want to use Tcl to as "the industry's first
scripting solution capable of handling enterprise-scale application
integration tasks" (quoted from Scriptics Tcl8.1 announcement) and they
are not interested to invent their own exception handling command before
they start doing their job.

Yes, this posting is a bit polemic and I do not expect to change your
mind. (It is enough if I reach the people at Scriptics. :-)

mo

unread,
May 7, 1999, 3:00:00 AM5/7/99
to
Alexandre Ferrieux wrote:
>
> mo wrote:
> >
> > how do I catch based on the type? As far as I can tell
> > there is no way to use the catch command like the
> > try {} catch {} finally {} statement in Java. For example, how
> > would I catch one type of error but not catch another type of
> > error without doing something nasty like this.
> >
> > if {[catch script err]} {
> > test for type 1
> > test for type 2
> > test for type 3
> > rethrow if not one of the ones you wanted
> > }
>
> This is exactly what a Tcl implementation of try..catch.finally would
> do. So what ? Are you complaining that it's not already in C ? I love
> the orthogonality of Tcl, i.e. its habit of providing independent raw
> primitives in C, leaving it to the programmer to add tons of syntactic
> sugar if he sees fit.
>
> -Alex


I am just saying that we need a "standard" way to catch and throw
exceptions
that also include a "type". Lots of extensions have a way to do this but
they are all different. We need one common way to catch and throw
multiple
exceptional conditions based on type in our Tcl code. That is all I was
saying. There is no need to throw out the current implementation, we
just
need a try-catch style command that does not catch every possible
exceptional
condition and leave it up to the user to figure out which one it was.

later
mo

Reply all
Reply to author
Forward
0 new messages