Article View: comp.std.c
Article #3971Situation indicators (long) (was: How to eliminate GOTO?)
From: Paul Long
Date: Mon, 11 Sep 1995 19:11
Date: Mon, 11 Sep 1995 19:11
167 lines
6839 bytes
6839 bytes
Situation indicators are something that you may not have heard about but are,
IMHO, a very elegant solution to the break-from-nested-loops and other
problems. The following C language construct is my adaptation of Knuth's, which
is in turn taken from C. T. Zahn. I can provide references if anyone is
interested.
Here is the _until_ statement, the situation-driven control construct. It
declares a situation indicator that has scope in the following statement, which
is typically an iteration or compound statement.
until <identifier>
<statement>
When the identifier is subsequently encountered in the statement, control
leaves the statement. IOW, control continues through the statement until this
situation occurs. That simple. Here is part of a tree-search-and-insertion
scheme from Knuth that uses a situation indicator with a for statement:
until leaf_replaced for (;;) {
if (a[i] < x) {
if (l[i] != 0) {
i = l[i];
}
else {
l[i] = j;
leaf_replaced;
}
}
else {
if (r[i] != 0 {
i = r[i];
}
else {
r[i] = j;
leaf_replaced;
}
}
}
a[j] = x; l[j] = 0; r[j] = 0; j = j + 1;
_until_ is not an iteration statement itself, e.g., it is not a repeat-until
statement, but it can be used with iteration statements. If you can get past a
tendency to read it in this way, it reads well. IMO, it reads a lot better than
gotos or breaks (I have absolutely NO use for the continue statement). This is
because gotos and breaks are used in terms of the mechanics of control and
looping, whereas situation indicators are used in terms of the problem. This is
due to their declaratory nature, as opposed to goto and return's active nature.
The situation indicator does not require a keyword to preceed it and is not a
statement. It would be integrated into the expression grammar and recognized
through semantic analysis in much the same way that an undeclared identifier
used in a function call is taken to be "extern int identifier();". No operator
can use a situation indicator as an operand. It might take a week or two to
integrate this language feature into an existing compiler. Not a big deal.
Note that the above example does not contain nested loops. Because of their
self-documenting nature (the indicator itself) and their ability to leave any
loop, situation indicators should be used instead of the break statement in all
instances, even for leaving a single loop. Like K&R function declarations and
definitions, break becomes obsolete.
Another use for situation indicators includes structured exception handling. I
DO NOT approve of this (as if it matters :-) ), but for those of you who like
this sort of thing, consider this version of the example taken from the "GOTO
single exit point" thread:
void manipulate_the_windows(Window *top)
{
Window *A = NULL, *B = NULL *C = NULL;
until error {
if (top == NULL)
error;
do_something_with_window(top);
A = get_subwindow(top);
if (A == NULL)
error;
do_something_different_with_window(A);
B = get_subwindow(A);
if (B == NULL)
error;
do_something_with_window(B);
C = get_subwindow(B);
if (C == NULL)
error;
/* All windows I'm looking for are good, so do it */
do_something_weird_with_four_windows(top,A,B,C);
return;
}
/* Do error handling here */
}
Actually, there is more to Zahn's construction. He and Knuth allow multiple
indicators and an optional _then_ clause that follows the statement. In C, the
entire thing might look like this:
until (<identifier1>, <identifier2>, ... <<identifierN>)
<statement>
then {
<identifier1> => <statement>
<identifier2> => <statement>
...
<identifierN> => <statement>
}
The _then_ clause provides separate "post-until" logic for each situation.
I dunno. Looks kinda awkward, but then C's for and switch syntax is pretty
ugly, too. I'd vote no on multiple situation indicators. It would really be
nice for robust structure exception handling, though, where each exception
could be identified separately in the code, such as end_of_file and read_error,
and each could have separate error-handling code. The above example could be
written like this:
void manipulate_the_windows(Window *top)
{
Window *A = NULL, *B = NULL *C = NULL;
until (no_window, no_subwindow, success) {
if (top == NULL)
no_window;
do_something_with_window(top);
A = get_subwindow(top);
if (A == NULL)
no_subwindow;
do_something_different_with_window(A);
B = get_subwindow(A);
if (B == NULL)
no_subwindow;
do_something_with_window(B);
C = get_subwindow(B);
if (C == NULL)
no_subwindow;
/* All windows I'm looking for are good, so do it */
do_something_weird_with_four_windows(top,A,B,C);
success;
}
then {
no_window => /* Do no-window error handling here */
no_subwindow => /* Do no-subwindow error handling here */
success => ;
}
}
Knuth also allows situation indicators to pass arguments to their counterparts
in the then clause. Nice, but we gotta draw the line somewhere. :-)
Although situation indicators would be really nifty, I'm also inclined to
reject them because they just make C a bigger language. There is some value in
not having a zillion ways to do something. What do you think?
--
Paul Long 45:29:14N 122:48:09W
plong@perf.com http://www.teleport.com/~pciwww/
"Wagging head and tail, the red-tailed fish, unsupported, turns around."
Technical Details
Message-ID:
<4321kd$cne@news0.rain.rg.net>Path:
arc1-ca.pugleaf.net!usenet.eel.ufl.edu!pacifier!rainrgnews0!usenetShow Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!usenet.eel.ufl.edu!pacifier!rainrgnews0!usenet From: Paul Long <plong@perf.com> Newsgroups: comp.std.c Subject: Situation indicators (long) (was: How to eliminate GOTO?) Date: 11 Sep 1995 19:11:09 GMT Organization: Performance Computing Incorporated Message-ID: <4321kd$cne@news0.rain.rg.net> NNTP-Posting-Host: yosemite.perf.com Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit X-Mailer: Mozilla 1.1N (X11; I; SunOS 4.1.1 sun4c) X-URL: news:comp.std.c?ALL