This is not necessarily the current version of this TIP.
| TIP: | 90 |
| Title: | Enable [return -code] in Control Structure Procs |
| Version: | $Revision: 1.9 $ |
| Authors: |
Don Porter <dgp at users dot sf dot net> Donal K. Fellows <fellowsd at cs dot man dot ac dot uk> |
| State: | Draft |
| Type: | Project |
| Tcl-Version: | 8.4 |
| Vote: | Pending |
| Created: | Friday, 15 March 2002 |
This TIP analyzes existing limitations on the coding of control structure commands as procs, and presents expanded forms of catch and return to remove those limitations.
It is a distinguishing feature of Tcl that everything is a command, including control structure functionality that in many other languages are part of the language itself, such as if, for, and switch. The command interface of Tcl, including both a return code and a result, allows extensions to create their own control structure commands.
Control structure commands have the feature that one or more of their arguments is a script, often called a body, meant to be evaluated in the caller's context. The control structure command exists to control whether, when, in what context, or how many times that script is evaluated. When the body is evaluated, however, it is intended to behave as if it were interpreted directly in the place of the control structure command.
The built-in commands of Tcl provide the ability for scripts themselves to define new commands. Notably, the proc command makes this possible. In addition, other commands such as catch, return, uplevel, and upvar offer enough control and access to the caller's context that it is possible to create new control structure commands for Tcl, entirely at the script level.
Almost.
There is one limitation that separates control structure commands created by proc from those created in C by a direct call to Tcl_Create(Obj)Command. It is most easily seen in the following example that compares the built-in command while to the command control::do created by proc in the control package of tcllib.
% package require control
% proc a {} {while 1 {return -code error}}
% proc b {} {control::do {return -code error} while 1}
% catch a
1
% catch b
0
The control structure command control::do fails to evaluate return -code error in such a way that it acts the same as if return -code error was evaluated directly within proc b.
There are two deficiencies in Tcl's built-in commands that lead to this incapacity in control structure commands defined by proc.
First, catch is not able to capture the information. Consider:
% set code [catch {
return -code error -errorinfo foo -errorcode bar baz
} message]
After evaluation, code contains "2" (TCL_RETURN), message contains "baz", ::errorInfo contains "foo", and ::errorCode contains "bar". But there is nothing accessible at the script level that contains the value passed to the -code option. That code is stored internally in the Tcl_Interp structure as interp->returnCode, but scripts cannot access that value.
Second, even if the information were available, there is no built-in command in Tcl that can be evaluated within the body of a proc to make the proc itself act as if it were the command return -code. Stated another way, it is not possible to create a command with proc that behaves exactly the same as return -code. Because of that, it is also not possible to create a command with proc that behaves exactly the same as while, if, etc. - any command that evaluates any of its arguments as a script in the caller's context.
This is a curious, and likely unintentional, limitation. Tcl goes to great lengths to be sure I can create my own break replacement with proc.
proc myBreak {} {return -code break}
It would be a welcome completion of Tcl's set of built-in commands to be able to create a replacement for every one of them using proc.
The return command shall have syntax:
return ?$option $value ...? ?$result?
There can be any number of $option $value pairs, and any value at all is acceptable for an $option argument. The legal values of a $value argument are limited for some $options, as follows:
the $value after a -code must be either an integer (32-bit only), or one of the strings, ok, error, return, break, or continue, just as in the 8.4 spec for return.
This proposal is implemented by Tcl Patch 531640 at SourceForge.
The prototype covers all described functionality, but might be further improved with more substantial bytecompiling of [return].
::errorInfo and ::errorCode could go away...
bgerror improvements.
This proposal is a synthesis of ideas from many sources. As best I can recall, major contributions came from Joe English, Andreas Leitgeb, and Kevin Kenny. If you like the idea, give them some credit; it you don't, blame me for combining the ideas badly.
Documentation for tcllib's control package: http://tcllib.sf.net/doc/control.html
This document has been placed in the public domain.
This is not necessarily the current version of this TIP.