Goto (Posting On Python-List Prohibited)
bartc
bc at freeuk.com
Sat Dec 30 09:41:09 EST 2017
On 30/12/2017 03:05, Lawrence D’Oliveiro wrote:
> On Saturday, December 30, 2017 at 12:12:23 PM UTC+13, bartc wrote:
>> Looking at 14 million lines of Linux kernel sources, which are in C,
>> over 100,000 of them use 'goto'. About one every 120 lines.
>
> That kind of thing leads to spaghetti code.
>
> Here <https://github.com/ldo/dvd_menu_animator> is an example I like to bring up: writing a Python extension module in C. As you know, this requires a lot of careful memory management to cope with errors and avoid either memory leaks or double-frees. The coding convention I came up with looks like this:
>
> ... initialize pointers to allocated storage to NULL ...
> do /*once*/
> {
> ... processing ...
> allocate some storage;
> if (error)
> break;
> ... more processing ...
> allocate more storage;
> if (error)
> break;
> ... even more processing ...
> }
> while (false);
> ... free allocated storage ...
>
> Basically, it becomes possible to satisfy yourself, by inspection, that every possible control path through the above code will pass once, and only once, through the storage deallocation.
>
> Things get slightly more complicated where allocation has to happen in a loop. Actually, that’s where the interesting cases happen. My technique can be adapted to cope elegantly with this, too--see the code.
>
I tend to use goto to share small sequences of code:
if cond1:
A
B
elif cond2:
C
elif cond3:
D
B
elif cond4:
C
...
Here, A, B, C, D represent small blocks of code. The conditions have to
be tested in this order.
B and C occur twice, so a goto is a quick way to reuse B and C without
needing to duplicate code, or go through the upheaval of extracting them
to functions. (And then the code develops so that the two Bs /are/
different, and then you have to get rid of the function. Or the second C
was temporary anyway.)
Any other way of doing it will obfuscate the structure:
if cond1:
A
elif cond2 or (not cond3 and cond4):
C
elif cond3:
D
if cond1 or (not cond2 and cond3):
B
I can no longer be sure if this right. Plus executing A, C, D can change
the conditions if they are tested again.
(I had introduced a special language feature just for this kind of
thing, but it was unsatisfactory. Goto was simpler and understood by
everyone. And portable to any other language - that hasn't done away
with goto. But it worked like this (not Python):
a:=20
case a
when 10 then
fred::
println "one"
when 20 then
@fred
println "two"
end
Output is "one" "two" when a is 20.
fred:: names a block, and @fred 'calls' that block, without having to
move it out of context. Actually this goes beyond what 'goto' can do, as
it can also 'come back'. But as you can see, it looks a bit naff. A bit
1970s.)
--
bartc
More information about the Python-list
mailing list