Re: goto
- From: Ben C <spamspam@xxxxxxxxx>
- Date: Tue, 14 Jul 2009 09:40:11 -0500
On 2009-07-06, Kaz Kylheku <kkylheku@xxxxxxxxx> wrote:
On 2009-07-06, Ben C <spamspam@xxxxxxxxx> wrote:
On 2009-07-06, Richard Tobin <richard@xxxxxxxxxxxxxxx> wrote:
In article <lnprcd3buf.fsf@xxxxxxxxxxxxxxx>,
Keith Thompson <kst-u@xxxxxxx> wrote:
IMHO, most legitimate uses of gotos are substitutes for missing
language features, most commonly either exception handling or
multi-level break. Note that both of these uses require only
forward-branching gotos.
One missing language feature that is naturally simulated with a
backward branch is tail recursion optimisation.
But who needs tail recursion when you've got loops?
Sufficiently advanced tail recursion can work across functions, and even across
compilation units. Looping is confined to a block of code.
But still I am intrigued, what are you doing here, basically just
goto-ing the top of the function again in order to "recurse"?
Under tail recursion, you are making a call which cannot return. Therefore, the
caller's local variables have no next use, and their memory can be purged prior
to the call.
A straightforward tail recursion to the same function is basically equivalent
to /assigning/ new values to the parameters, and branching backwards.
So for instance a the loop for (i = 0; i < 100; i++) stmt; goes something like:
void forloop(int i, int n)
{
if (i < n) { // guard
stmt;
forloop(i + 1, n); // increment and branch backwards
}
}
// ...
forloop(0, 100);
This can be turned into the code:
void forloop(int i, int n)
{
label:
if (i < n) { // guard
stmt;
i = i + 1; // set up the new parameters
n = n; // <- likely optimized away
goto label; // pass the control
}
}
In Lisp, I have experimented with parametrized goto, which then became portable
tail recursion. (Search the comp.lang.lisp archives for "argtags").
The idea is this. Suppose that goto labels could have parameters: the names of
existing variables. And supose that goto could supply argument values. Then you
could write the above like this:
label(i, n): // all names in brackets must be declared variables
// ...
goto label(i + 1, n);
And perhaps the need for the goto could disappear into the syntax also:
label(i, n):
// ...
label(i + 1, n);
Now this simple syntactic sugar almost looks like function calls.
And also almost like for loops :) Although I take the point you can do
this across functions.
It's a useful extra discipline in the goto. The problem with many uses
of goto is that they don't make it clear what state changes are
relevant. It's the assignments that are the problem. We are puzzled by
a backward goto because we don't know what is different the second and
subsequent time around the same block.
Yes I think that's right. But wouldn't it be simpler just to demand that
compilers optimize tail recursion, as some do anyway, and then just
write recursive code in the normal way?
Or, simpler still, not demand that and just stop wanting optimized tail
recursion in C and use the more idiomatic alternative (loops) instead.
Above we know that what is different is that i is incrementing by one.
Suppose that, further, we take on the discipline that we will avoid
assignments in the code. Suppose that all assignments are disguised
using the the label(arg, ...) syntax. Then the gotos become much
easier to understand.
You know which variables are pertinent to a basic block headed by a
label, and whow they change. Each parametrized goto explicitly spells
out values for every single one of those variables used in that basic
block, even the ones that don't change, like n above. All of the
arguments are required, so you can't miss anything; you must specify
what happens to every darn thing. Moreover, you can quickly scan a
block of code to see whether it depends on any variables that are not
mentioned in its preceding label; they can be added to the label, and
then you can reason about all of the goto places which reach that
label: how should they compute the value of that variable? Which ones
should leave the variable alone, and which ones should change it? So
you're not left wondering ``what is the purpose of this i = 42
assignment here, and how does it affect the previous code after some
backward branch is taken''.
Arguably, it's the state change in imperative programming which is the
real cuprit, not goto. Eliminate the assignment and it all starts to
look functional.
Well, this would be an interesting way to do things, and you could
implement it fairly easily with a little preprocessor on top of C.
.
- Follow-Ups:
- Re: goto
- From: Nobody
- Re: goto
- References:
- Prev by Date: Re: tutorials
- Next by Date: Re: HELP..............
- Previous by thread: Re: goto
- Next by thread: Re: goto
- Index(es):
Relevant Pages
|
Loading