I continue this entry from my defense of duplicated code. If programmers were politicians, writing an article like this would surely prevent me from ever running for Programmer President. Twenty years from now someone would dig it up and say "Lucas Pierce supports the use of go to! Heresy!".
That said, let's say we have been contracted to write a program to generate Fibonacci numbers. Believe me, Fibonacci generators are a hot commodity these days so this is a totally realistic example. In this case you run the program and then type in a number (n) and it gives the first n Fibonacci numbers and then exits.
main
integer n = console.getInt()
integer first = 0
integer second = 1
integer next
fib_loop:
print first
next = first + second
first = second
second = next
n = n - 1
if (n > 0) goto fib_loop
end
<sarcasm_tags_for_the_clueless>Egads! That program is totally obtuse! Here let me write a version without go to so that it makes more sense</sarcasm_tags_for_the_clueless>:
main
integer n = console.getInt()
integer first = 0
integer second = 1
integer next
do
print first
next = first + second
first = second
second = next
n = n - 1
while (n > 0)
end
Now it makes sense! Although we could use a for loop to make it even better:
main
integer first = 0
integer second = 1
integer next
for (integer n = console.getInt(); n > 0; n = n - 1)
print first
next = first + second
first = second
second = next
end
end
Why is this version so much better than the go to version though? We've all been taught go to is evil but I find all three equally readable. This is me throwing down the gauntlet, I challenge you to tell me why go to is wrong.
This is a commonly cited example.
When using a goto that is quite literally the same as a loop, the only problem is having to learn multiple methods of doing the same thing. But we're already sacrificed that by having both a do-while option and a for loop option.
The problem arises when you start using goto's elsewhere, it seriously detracts from the readability. We've learned to accept the construct of loops, they're easier for people to understand than trying to follow jumping logic.
It's alot like parenting. It's easier to simply forbid an R movie than to explain what parts are too mature or to selectively show parts of the movie.
Posted by: Peter Youngs | December 08, 2008 at 10:10 AM
Pete's absolutely right. "Goto"s used as loop replacements are not the cause of the community's ridicule of the construct. Instead, it was a sudden surge in the popularity using goto to create "spaghetti code" that earned it its reputation.
This is not to say that all "goto" use is evil or incorrect. For example, a goto may be used to provide a single exit point for a method, which in some cases can increase readability (some may disagree with me on this).
A "good" software developer knows the pros, cons, and appropriate situations to utilize the design/keyword/technology/language at hand. Blindly re-using the same solution to every problem is what causes the problem; that's the real point behind Dijkstra's infamous "Goto Statement Considered Harmful".
Posted by: Nick Lynch | December 08, 2008 at 01:58 PM
Pete, why is a loop an easier construct than jumping? Most business people can follow a flow chart, they are a pretty common and easy device for showing the progression of something. A go to is basically just a flow chart.
On the other hand if you are talking about implementing an algorithm, recursion/pattern matching is a more natural and direct translation. For instance the Haskell version of the fibonacci sequence is:
fib :: Integer -> Integer
fib 0 = 0
fib 1 = 1
fib n = fib (n-1) + fib (n-2)
We are all used to iterations and structured procedural programming because that is what we grew up with, but I don't think that means it is inherently easier.
Nick, so you are saying that go to was overused for situations where it wasn't the appropriate technology. Why was go to not appropriate for every situation? If we learned anything from C++ it is that they went overboard with the complexity of the language itself. Why is it justified to add to a language for loops, while loops, do while loops, exception handling, switch statements, break and continue when go to can easily do all of this with go to? What are these constructs actually buying you?
Posted by: Lucas Pierce | December 08, 2008 at 04:43 PM
"Why is it justified to add to a language for loops, while loops, do while loops, exception handling, switch statements, break and continue when go to can easily do all of this with go to? What are these constructs actually buying you?"
Scoping?
Also, the timeless essay:
GOTO Considered Harmful
http://www.cs.utexas.edu/users/EWD/ewd02xx/EWD215.PDF
Posted by: Andrew Harrison | December 10, 2008 at 02:59 PM
I can scope my go to version without needing any new loop statements. See below:
{
fib_loop:
print first
next = first + second
first = second
second = next
n = n - 1
if (n > 0) goto fib_loop
}
Posted by: Lucas Pierce | December 10, 2008 at 07:06 PM
"Why is it justified to add to a language for loops, while loops, do while loops, exception handling, switch statements, break and continue when go to can easily do all of this with go to?"
I think the simple [but subjective] answer is readability. The above examples have been with a single simple loop; I think looking at some more complex code examples would lead even you to declare the goto versions less readable.
I believe there's a reason for that; the language constructs we've all grown to love all carry with them something that goto does not - intent. Bear with me on this:
When you see a for loop in the code, you know what the intent of that loop is. It will perform some initialization, then loop until the condition is met; there is some comfort in this familiarity. Contrast this to a goto; every goto statement you see must be evaluated for context and intent. The goto statement may be jumping back up to the top of a "loop", out of the loop, or into a different function altogether. You don't know what the intent is until you've tracked down the target.
Now, as previously mentioned, if we just replace all of our while or for loops with gotos, I don't think the Terminator is going to come back in time to blow up our CPUs. :). The problem is when some zealous programmer starts using gotos to do all the while loops, and for loops, and switch statements, and interfunction jumping, .... you get the point. Each goto encountered is a brand new beast, and you have to track down what and why it's doing what it's doing.
Counterpoint?
Posted by: Nick Lynch | December 11, 2008 at 03:01 AM
http://xkcd.com/292/
Posted by: daZip | February 04, 2009 at 12:16 AM