38
$\begingroup$

I was recently reading a new, and mostly excellent, magazine Hello, World. There is an article on teaching goto. The author states that there is value in teaching goto, as it helps to translate flowcharts into code.

I have always considered goto to be harmful. It results in code that is buggy and hard to read. Not just because I read it in a 1960 paper “Go To Statement Considered Harmful“ — Edsger W. Dijkstra, but because it is self evident (once you have tried structured-programming).

I have always considered flow-charts the same way. They are just the pictorial form of unstructured code (The UML of assembly language).

So the question:

Does the author have a point? Is there some value in goto or flow-charts?

I accept that:

  • Flowcharts are visual, but there are visual structured representations that are better.
  • goto can/has-to be used in teaching assembly language/machine code.

One of many links to the paper “Go To Statement Considered Harmful

$\endgroup$
22
  • 13
    $\begingroup$ I disagree that goto has no place; I would agree that there is little value in teaching it to new programmers: it can be mentioned (and discouraged) and they can work it out for themselves when (if) they need it. There is nothing to it if you can already 'read' code, and one is more likely to understand why it is generally inadvisable with an existing understanding of higher-level flow-control techniques (as opposed to "Here is goto! NEVER USE IT") $\endgroup$ Sep 27, 2017 at 18:29
  • 28
    $\begingroup$ As an old programmer (learned on a TRS-80 in 1980), I think that teaching GOTO is a good idea, because it teaches the students that at the bottom of all that fancy flow control and OO stuff are nothing but jumps (both conditional and unconditional) and pointers. $\endgroup$
    – RonJohn
    Sep 27, 2017 at 20:32
  • 8
    $\begingroup$ You'd be surprised how many people don't seem to get "the computer does things in the order they're written" - flowcharts might help explain that. $\endgroup$
    – user253751
    Sep 27, 2017 at 23:31
  • 7
    $\begingroup$ @immibis "computer doing things in order" : a typical misunderstanding is thinking that during a while ( x != 0) { statements; }, the x variable is monitored during the statements execution, and the loop break as soon as x gets the value 0. $\endgroup$ Sep 28, 2017 at 6:59
  • 40
    $\begingroup$ If you don't teach the kids about goto, they will learn it on the streets. $\endgroup$ Sep 28, 2017 at 7:50

16 Answers 16

5
$\begingroup$

If you are teaching assembly code or maybe Fortran then probably you need to discuss goto and possibly flow charts. However, if you are teaching a modern high level language, even something as old as Pascal, you should probably avoid them other than as an historic curiosity. This was settled almost 50 years ago, actually.

Along with some other illuminati of CS, David Gries has always used the term "flaw chart" for the classic diagraming technique. It is too easy with such tools to create unmaintainable code.

There is a form of Structured Flow Chart, however, which is not much different from, say, Pascal. It has no arrows, but, basically, only containment and sequencing of structures. But even that is probably just a waste of time as the constructs of modern languages make it unnecessary.

Even if you are programming in a language that requires goto however, you should probably only use structures like if-then and while-do that have been proven to be sufficient and also result in better (maintainable, understandable) code. Just Say No.

On the other hand, there is one reason for teaching goto to students of modern languages. If those languages permit goto then eventually the student will need to read programs that contain them even if they don't write such programs. So, purely as a defensive measure, they should know how to interpret these programs even as they disparage the authors of those programs.

There is a story from the past that is illuminating. In the old days IBM had a company policy that every program had to be documented with flow charts. However, they also had a tool that would create a flow chart from a Fortran program. So, the program was written, then the tool produced its flow chart, often spread over many, many pages. But the policy was satisfied. But, as a design tool, no.

See: https://en.wikipedia.org/wiki/Considered_harmful

$\endgroup$
7
  • 1
    $\begingroup$ I have used a tool to automaticaly create UML class diagrams form code. Because we needed them, it was policy. $\endgroup$ Sep 27, 2017 at 18:29
  • 6
    $\begingroup$ Flowcharts work well as a tool to define/describe the desired flow (on a higher level) of a program. They can be important tools when explaining your program to a stakeholder or when attempting to grasp a new subject domain that you are developing for. I would argue they're not a waste of time to learn when used correctly. $\endgroup$
    – Ben.12
    Sep 27, 2017 at 19:51
  • $\begingroup$ There are cases where you really need goto or labelled break. Example : outer_loop : for (X x : list_of_X) { for (Y y: list_of_Y) { if (some_condition(x,y)) { do_something_with(x,y); break outer_loop; } } $\endgroup$ Sep 28, 2017 at 9:01
  • $\begingroup$ Well, need is relative. You have set up a case in which a targeted break is really convenient but there are other solutions to such a problem. Otherwise Python programmers would be just stuck. $\endgroup$
    – Buffy
    Sep 28, 2017 at 11:13
  • 1
    $\begingroup$ @Buffy have you actually USED Fortran in the 20 years or so? You do realize it now even has classes? - plus a whole range of other "structured" features of course. Sure, there are one or two things that still need the concept of gotos and statement labels (like low-level error handling in I/O statements) but those are very much a minority - and of course you can (and should!) encapsulate the low-level I/O in its own classes and/or modules, so the implementation is invisible to the rest of the program! Teaching people Fortran IV is about half a century out of date now. $\endgroup$
    – alephzero
    Sep 29, 2017 at 3:03
61
$\begingroup$

I am the author of the article. The point is to simplify the model of computation, not to match flow charts.

This is for mixed-ability 12 year olds, and when I say mixed, I mean some still add single digit numbers using their fingers.

Flow charts work because you can easily jump to another point in the program. This is not software engineering. I want them to create software where they understand how it works.

Goto also more closely mirrors the processor: it's easier to describe how programs are translated. After all, there is no such thing as structured programming at machine code level.

Dijkstra's article is a polemic from a purist. There were dissenting views at the time, which gave a more nuanced picture. The Wikipedia page on the article has good links on this.

Most new programmers shun goto because they have been warned it is evil, bad, and wrong rather than a more considered opinion.

My GCSE students learn structured C++. I myself am a CS grad and was a professional programmer a number of years ago.

$\endgroup$
9
  • 20
    $\begingroup$ People should actually read Dijkstra's letter. He states the less gotos, the better. The context at the time was "goto's for everything", including decision and repetitions. Dijsktra advocated that programming languages should include constructs (like while/repeat until, if-then-else) helping to avoid the use of goto. Didn't say that loops/if-then-else were sufficient constructs to get clear code without gotos (talks about Jacopini's theoretical way to eliminate all gotos, where euphemistically "the resulting flow diagram cannot be expected to be more transparent than the original one"). $\endgroup$ Sep 28, 2017 at 7:20
  • 8
    $\begingroup$ Yes, Dijkstra was a purist. He was also extremely arrogant. But he wasn't wrong as I think you are trying to imply. Yes, there was controversy about his claims at the time, but the paper influenced the development of every later language. It has taken a while to eliminate goto altogether, of course, but the trend is now nearly complete. $\endgroup$
    – Buffy
    Sep 28, 2017 at 15:51
  • 2
    $\begingroup$ @Buffy Dijkstra's paper protects (in part) against these practices.The thing is, those practices aren't supported by higher level languages. It was absolutely correct when he wrote it, but technology has changed. It's like us sticking with QWERTY. Back when it was designed, it made sense. Now, it doesn't at all. Obviously, I'm not switching to DVORAK anytime soon, but can we at least agree that advice from 50 years ago using different technology might not be the gold standard for the technology we have today? $\endgroup$ Sep 28, 2017 at 16:35
  • 11
    $\begingroup$ Dijkstra was right for most cases and purposes. Can I just ask if people criticising the approach have any experience of trying to teach low ability 12 year old children? When I trained to teach my biggest problem is I thought I could just explain things and children would understand. In reality I had been hanging out with the top 10% of the ability range (even in school I had no idea about the struggle of bottom sets.) I also teach year 11 maths and pupils struggle with place and value along with adding negative numbers. It is a different world. $\endgroup$ Sep 28, 2017 at 17:19
  • 9
    $\begingroup$ @PaulPowell I have taught exactly one 12 year old to code (although to be fair, it was me). In support of what you're saying, I was learning TI-BASIC, so I learned what a goto was before a for-loop, and it made perfect sense. "Computers always read the next line of code unless you tell it to jump to a different line instead." Can't get much easier than that. When I got to loops and method calls which implicitly jump around, the first thing I'd do was mentally stick the gotos in and then they made sense too. I couldn't imagine learning loops first (or, god forbid, how a stack pointer works). $\endgroup$ Sep 28, 2017 at 17:38
17
$\begingroup$

Why do you learn about bits and bytes if modern languages, with good reason, abstract from it? Why do we learn to program in assembler if modern languages, for good reason, abstract from it? Why do we learn bare-metal imperative programming if object oriented languages, with good reason, encapsulate it? Why do we learn C even though C++ offers much better ways to express ourselves? Why do we learn naked pointer semantics if smart pointers are the way to go?

The reason is that the less abstract concepts are the building blocks for the more abstract ones. (And, I might add, there are times when it is appropriate to be less abstract. There are times to use assembler, and goto, and pointers.) It helps to know assembler when you try to understand C. It also helps appreciating what the language does for you. Knowing C, in turn, makes you understand C++ better (both its rationale and its limitations!).1

It helps to know goto when you learn about loops, and what they do for you.

The same way it helps to know molecules if you try to understand a cell.


1 It is also important to understand that machine independence and structured programming and object orientation are essentially concepts which are just more or less supported by the different languages. You certainly can write well-structured assembler. OO crept into my C after I grokked C++.

$\endgroup$
2
  • 3
    $\begingroup$ I think one of the best reasons to teach goto is so that people understand why it's problematic. Often old bad ideas are recycled in software and it's the people that don't know the old ways that get suckered. While your at it build an app in VB where all the code is buried in button events. Then change the requirements. Same goes for doodleware. $\endgroup$
    – JimmyJames
    Sep 28, 2017 at 14:42
  • $\begingroup$ reminiscent of the Law of Leaky Abstractions joelonsoftware.com/2002/11/11/the-law-of-leaky-abstractions $\endgroup$
    – Jodrell
    Oct 2, 2017 at 12:33
12
$\begingroup$

Don't teach it if you want Programmers (know what they're doing). Do teach it if you want Computer Scientists (know why they're doing it).

Obviously these two aren't mutually exclusive, but plenty of people learn how to code without understanding what they're doing at a lower level, and that's ok. If that's your goal, ignore goto; they'll never need to know it.

If you do want them to understand the why, then you have to teach it. If their code uses any sort of control flow, then at a lower level something somewhere is calling a goto (or something close), and CS students need to understand how that works.

EDIT: I just reread GOTO Statement Considered Harmful and it actually ends with:

The exercise to translate an arbitrary flow diagram more or less mechanically into a jump-less one, however, is not to be recommended. Then the resulting flow diagram cannot be expected to be more transparent than the original one.

I know most of us have focused on the goto side of this question, hopefully this sheds some light on the flowchart side as well.

This line also reads to me as a confirmation that goto should be learned as a concept, since describing a control flow is nearly impossible without it, but Dijkstra still advocates avoiding it in code.

$\endgroup$
11
  • 1
    $\begingroup$ Hey LordFarquaad! Welcome to Computer Science Educators! $\endgroup$
    – thesecretmaster
    Sep 27, 2017 at 20:59
  • 1
    $\begingroup$ Don't forget that COBOL is still the most prolific language out there, and all of the flow control in COBOL is through equivalents to GOTO $\endgroup$
    – pojo-guy
    Sep 28, 2017 at 1:57
  • 1
    $\begingroup$ Although this makes sense as an answer, I'm not sure it will help the subset of teachers most at risk of incorrectly introducing GOTO to their cohort. $\endgroup$ Sep 28, 2017 at 7:23
  • $\begingroup$ Well, @pojo-guy, you really should update to COBOL 85 or more recent. Cobol 74 really was a pain in the ***, but since 1985 it has all you need for structured programming : loops, if then else, and even a very interesting EVALUATE verb, much more powerful than the rudimentary switch of C/C++/Java etc :-) $\endgroup$ Sep 28, 2017 at 14:07
  • $\begingroup$ I agree that Evaluate is much more powerful than "switch", but COBOL is crippled in other ways. Problems that take three lines of java code can take hundreds of lines of COBOL code - for example finding the intersection set of two sets. Each language expresses different thoughts easily, so they are all valuable. $\endgroup$
    – pojo-guy
    Sep 28, 2017 at 17:33
9
$\begingroup$

I think the goto is sorely maligned. When Edsger Dijkstra wrote his famous letter in 1968, high level languages were not the same as they are today, and the goto could easily be abused.

In my early days learning FORTRAN IV, the goto was an important part of the language and many of the important modern structures were not yet universally mainstream. The resulting code could indeed lead to a degree of complexity which would be hard to analyse.

High level languages were meant to be more abstracted than machine languages, and you would have thought manually encoding the structure this way was a failure in this regard. If that sounds like a strong argument against goto, then, well, it is.

However, things have moved on since then, and the alternatives are not always better. In fact the goto is still there in spirit every time we use the switch statement in c-type languages, as it is all but a specialised goto. This explains why you then need to end each part with a break statement.

Modern languages tend to restrict the use of goto to minimise the damage it could do in the past. In particular, you can’t just arbitrarily goto anywhere, but it must be within the limits of the current block, and only to labelled, not numbered, locations.

If you add further self-imposed restrictions such as only going forward, or only using it in certain circumstances, it can certainly be used in an orderly manner.

For example:

  • You can exit a function early with a return statement or a loop early with either continue or break. There is no standard early exit for an if block, but a goto to a label after the block will do nicely.

  • For testing and trouble-shooting, it may be useful to skip earlier parts of the code and go straight to the section in question. Wrapping these earlier parts inside an if block simply to skip them is counter-intuitive and unnecessary.

The point is, every programming structure has its pitfalls and can be abused. goto has possibly been more abused than the others. However, there is still a case for using it in well-controlled circumstances, as it can help make the code easier to follow.

So yes, there is value in teaching goto.

As regards flow charts, I think that they remain the most obvious way of visualising a process. The fact that they are used so often in non-technical contexts attests to this. When teaching programming I often end up drawing arrows all over the structures.

I’m not sure that I would take flow charts too formally, though. They are useful in visualising, but I certainly don’t think they’re necessarily the best way to plan a program.

$\endgroup$
6
  • $\begingroup$ I agree that flow charts in non-programming contexts is often good. For example, to describe a manual procedure. Flowcharts are an abstraction of unstructured code, such as assembler. If your machine is a human, then this is appropriate. $\endgroup$ Sep 28, 2017 at 8:37
  • 1
    $\begingroup$ A former colleague of mine used GOTO as "elegant recovery from inelegant situations" --- dealing with catastrophic error conditions. $\endgroup$
    – Peter K.
    Sep 28, 2017 at 22:18
  • 1
    $\begingroup$ @PeterK.: A specific example: error handling in a C function that took a lock. linux/mm/msync.c uses goto out_unlock; inside many error-check if() clauses. It implements a system call, so all its args are untrusted, and there are many return-error cases that are only detected after taking a lock. It's C, so RAII to release the lock isn't an option. Obviously this applies to any other cleanup task that you don't / can't use RAII for in whatever language. $\endgroup$ Sep 29, 2017 at 14:11
  • $\begingroup$ Can also be used for breaking out of a double-nested loop, although that's getting into spaghetti territory if done too much. Some languages have a break label for this. e.g. PERL has next LABEL for outer loops. Still possible to abuse, though. $\endgroup$ Sep 29, 2017 at 14:14
  • $\begingroup$ @PeterCordes actually you can use deeply-nested ifs to do the same thing. A real anti-goto purist would make you do that. It's not as much of a readibility problem on modern wide monitors... $\endgroup$
    – user253751
    Oct 1, 2017 at 4:46
9
$\begingroup$

I teach them within assembly code. Otherwise, I mention them within my Java class when I teach their modern-day analogues, break and continue. This is late in my AP course, after the AP test is over. I present the two statements as restricted versions of JMP (that's the 6502 Assembly syntax for goto), and I then follow up with two questions. They get to discuss it out in small groups before we rejoin as a class and go over it together. This gives them a chance to discover through peer discussion how language restrictions can really ultimately help us.

  1. There are several more JMP statements that break program flow in Java. Can you find any? (return, throw, System.exit())

  2. Why, do they suppose, does Java restrict our JMP capabilities to very specific situations? What would be the problem with giving us an unhindered jump command in Java?

$\endgroup$
6
  • 1
    $\begingroup$ There is a fourth one: throw. $\endgroup$ Sep 27, 2017 at 21:10
  • 1
    $\begingroup$ @PaŭloEbermann And System.exit(). $\endgroup$ Sep 27, 2017 at 22:25
  • 1
    $\begingroup$ Also note that the Java virtual machine bytecode has unconditional jumps (of course). It could be instructive to show the bytecode for loops and conditional expressions (instead of comparing unrelated 6502 assembler). $\endgroup$ Sep 27, 2017 at 22:33
  • 1
    $\begingroup$ @PeterA.Schneider 6502 is useful for me because it is what they have studied, so it's a good point of reference. It's also a beautifully clean and simple assembly language $\endgroup$
    – Ben I.
    Sep 28, 2017 at 1:51
  • $\begingroup$ And a fifth one: switch $\endgroup$
    – Manngo
    Sep 28, 2017 at 8:57
6
$\begingroup$

Flowcharts are a useful tool to understand programs that perform moderately complex sequences of interactions. They aren't always a good way to describe an algorithm, but they are a good way to describe the behavior of a system that reacts to external events in different ways depending on its state, with a non-linear control flow. Note that by flowchart, I'm not referring to a specific formalism — at this level of detail, I might as well call it a state diagram (although a proper state diagram requires a more precise understanding of what the different system states are before you can draw it). Flowcharts have their place in an imperative programming course, but only at a fairly advanced stage, after the students are familiar with basic control structures such as conditionals, loops and subroutines. They're a visual aid to understand complex control or data flow, in the same way that decision diagrams are a visual aid for complex series of conditionals.

The only good reason I can think of to introduce flowcharts early on is if the students started with a style of visual programming that resembles flowcharts. Otherwise, teach while loops first.

Goto is an instruction that's hard to really understand. (If you think it's just a jump, you don't understand goto.) It's perfectly fine to teach imperative programming without goto, if you're doing it at any level that's higher than assembly (in which case what you'd teach is jumps). Goto is very rarely useful in the real world and is rarely used. Its place in a basic or intermediate imperative programming course is as an incidental mention, as something that exists, that you mention for the students' interest but isn't part of the curriculum and won't be on the exam.

I work in industry. I write software for embedded systems in C. Think I should be insisting on the importance of goto? Wrong. In my world, goto is almost exclusively used for one thing: a forward-only goto, a generalization of break that allows breaking to the end of any block. The single common idiomatic use of goto is to jump to a common cleanup code before returning from a function in C:

int myfunction () {
    foo_t resource1;
    bar_t resource2;
    resource1 = allocate1();
    if (!resource1) goto cleanup;
    resource2 = allocate2();
    if (!resource2) goto cleanup;
    if (!do_stuff()) goto cleanup;
    …
    return 1;
  cleanup:
    free2(resource2);
    free1(resource1);
    return 0;
}

Many coding standards for embedded programming forbid using goto for anything else. In languages that have a better clean-up mechanism, such as try/finally or C++ destructors, goto is useless.

Understanding goto is a secondary skill for programmers, part of understanding how a program's code relates to the way the machine executes the program. A good programmer understands goto, but a decent programmer understands how to program without goto. The primary skill for a programmer is understanding how a program works, not understanding how a machine works. (There are exceptions, obviously — I write OS code, doing things like memory management and context switching and accessing peripherals, and that obviously requires a precise understanding of how the machine works. But that's a highly specialized field.)

The real difficulty with goto is, as I mentioned before, that it isn't just a jump. It's a jump to a different context. The invariants that hold at the location of the jump may not hold at the target location. A goto introduces a non-local connection between two points in a program that makes it hard to figure out how the program state evolves and what invariants hold.

Paul Powell's statement that “GOTO (…) is easy to understand” is just wrong. What's easy to understand is how a machine executes a goto statement. But the most important part, understanding how a program that uses goto works, is difficult. The statement that “it can be used to explain what loops and other items of structured programming actually are” also completely misses the point. Goto can explain how structured programming items are implemented on a processor. It explains an implementation, not the concept. Goto is an advanced step after structured imperative programming, not a step before.

Using goto to encode flowcharts is also very misguided. With goto, “we can code directly from a flow chart” — this is true: goto makes it easier to write a program from a flowchart without understanding how the program works, without figuring out the structure in the flow of events. But when you do that, you end up with a write-only program. Sure, you've been able to write it, but you won't be able to explain its behavior when a parameter that isn't reflected in the flowchart turns out to be important, or to modify it in a way that isn't easy to draw on the chart. Write-only programming is the mark of a mediocre programmer, capable only to fumble in the dark until they somehow manage to pass the tests.

Goto has its place when you teach how a machine executes code. It's what's happening under the hood. It has little to no place in teaching how to program, and Dijkstra would be quite right to complain about its use in this context.

$\endgroup$
17
  • $\begingroup$ And your experience of delivering this knowledge to 28 mixed ability 11 year olds is? $\endgroup$ Sep 29, 2017 at 7:18
  • $\begingroup$ @PaulPowell Teaching goto is not the problem. It may even be easier that teaching structured programming. But then you have a class full of pupils that need to be un-taught. I have been in gilles position, and have had people on my team that have been taught these bad habits. It can take longer to un-teach them, than it took you to teach them. Use scratch as a basis (this is taught to 7 year olds), then have them translate scratch programs into python (see cseducators.stackexchange.com/a/178/204 ). Both languages do not have goto. $\endgroup$ Sep 29, 2017 at 8:05
  • $\begingroup$ I am an experienced Head of Department with a degree in Computer Science and 12 years in industry. Do you really think I have not tried this or thought about it? $\endgroup$ Sep 29, 2017 at 10:22
  • 1
    $\begingroup$ Real-world example of goto for cleanup: linux/mm/msync.c uses goto out_unlock; inside many error-check if() clauses. It implements a system call, so all its args are untrusted, and there are many return-error cases that are only detected after taking a lock. It's C, so RAII to release the lock isn't an option. (There are 12,987 hits for goto in the Linux kernel tree; all like this or asm goto as a way of optimizing if (asm_statement) to avoid producing an actual boolean.) $\endgroup$ Sep 29, 2017 at 14:23
  • 2
    $\begingroup$ @PaulPowell I don't have any experience teaching this to 11 year olds, but I have as much industry experience, and I'm telling you that your teaching will neither make them better programmers nor make it easier for them to learn. The example you cite from the Linux kernel is an example of the pattern I state as being the only common use case for goto in my world. $\endgroup$ Sep 29, 2017 at 16:36
4
$\begingroup$

I teach a college level introductory computer science course, where the primary goal is to learn programming in Java with no assumed prior programming experience.

I do teach flow charting when I cover decision making & looping. Flowcharts aren't a great tool for an entire non-trivial program. They are a reasonable tool for high level algorithm design and for code level representation of methods. Furthermore, most students have seen a flowchart of some type before & I find that any degree of familiarity is helpful to those who find programming to be an otherwise foreign concept. I need to reach as many of my students as possible & find flowcharts to be worth leveraging in that regard.

I do not cover use of goto beyond stating that it exists, it's easy to misuse and typically by the time they might encounter it in a production environment, they should have accumulated enough programming acumen to deal with it as needed. It's not a core piece of the language & there's plenty of other material that sees more routine usage that could use its time.

$\endgroup$
4
$\begingroup$

The real question here seems more like when should you teach goto rather than if you should teach it.

The first example programs should certainly not be looking like those we wrote on the machines in WH Smith on the way home from school:

10 PRINT "HELLO WORLD!"  
20 GOTO 10

A while true construct is more sensible here. However, if you introduce your students to programming by demonstrating the low-level operation of the CPU (fetch/decode/execute) then it's more likely that you'll need a force-pc (although typically it also needs to be conditional).

The assembly language constructs typically don't quite match high-level languages exactly (e.g. count down rather than up, in a loop to allow compare-and-branch-if-zero), but at some point your course will probably link high level languages to machine operations.

To clarify, I'm not suggesting that it is sensible to start by introducing the full scope of:

 while (expression == TRUE) {stuff, including maybe break};

rather keep the templates simple and expand the linguistic elements progressively. while (TRUE) is just a compound keyword when it's first needed, just like GOTO <LABEL>.

It should be easy to explain that modern high level languages are designed so that humans can understand the code. That is why there are usually several different ways of expressing control flow even though to a beginner they all look interchangeable. In the absence of any more specific reason, goto is likely to come at the end of your list of 'possible control flow changes' and probably needs to be introduced as an instruction which has been mostly replaced in modern programming, because other constructs are better, not simply because goto is bad.

The best reason I can think of for introducing goto is that the concept might help when it comes to explaining hardware interrupts (being the most important part of CPU architecture which isn't even mentioned in far too many courses).

$\endgroup$
9
  • 2
    $\begingroup$ Why is while(true): in any way more sensible? Write down a full explanation of how the two bits of code work. Which is simpler to understand? $\endgroup$ Sep 28, 2017 at 13:42
  • 2
    $\begingroup$ @PaulPowell It might be interesting if you ask your question about how control flow teaching is leaving gaps - particularly if you have specific student groups in mind. $\endgroup$ Sep 28, 2017 at 13:59
  • 1
    $\begingroup$ @sean I think it is simpler than leaving gaps. It is about a student being able to express themselves in code. Did you try writing down a full explanation of while true? $\endgroup$ Sep 28, 2017 at 14:15
  • 1
    $\begingroup$ Really awkward leaving comments here as I can only access it on mobile at the moment. $\endgroup$ Sep 28, 2017 at 14:16
  • 1
    $\begingroup$ @jrh - See edit. $\endgroup$ Sep 29, 2017 at 13:04
3
$\begingroup$

Binary digital computers (and the execution of most programming languages) are just big state machines at their very heart. State machines usually require non-sequential state changes. e.g. gotos

A flow chart is a form of state machine. (superset or subset?)

You need goto's to learn jump statements in assembly language, asm to learn machine code, and machine code to understand CPU architecture and design. Understanding computer hardware logic and state machines seems important to any CS degree. As for difficulty of learning machine code, many thousands of student-aged kids learned to poke 6502 and Z80 op codes back in the day...

$\endgroup$
2
$\begingroup$

I will concern myself mostly with goto, but first a little on flow charts.

On Flow charts

I see flow charts as just a ways to visually represent goto-ful low-level algorithms/code.

What flow charts are not

Some other answers have mixed up their use with state-machines, or decision trees. Doing this could result in coding each code path separately, this would result in an undesirable increased program-size. For example for a sorting algorithm, of we could get a code size complexity of $O(n!)$. This does not scale, much beyond sorting 3 items, and you will use all of you computers memory (just for the program to sort 16 items).

Good uses of flow charts

The low-level nature of flowcharts can be of great value, when creating a procedure to be carried out by humans. I.e. A first aid flowchart.

On goto statement and goto

In the paper “Go To Statement Considered Harmful”, Dijkstra is concerned with the goto statement, not with goto. He points out that all higher order structures will use goto in their implementation. According to Dijkstra, this implementation is not the problem, only the direct use of goto. In the time since his paper the structure he mentions, if, else, while, for, until, repeat, and sub-routines have been part of our high-level languages. For his call was not for us to stop using it in programs, but to create languages that did not require it, and then to stop using it. And in the meantime to use it only in a structured way, to simulate the structures. Therefore only use it if your language does not provide the high-level structure that you need, and know which structure you are simulating (don't ad-hok it).

For a number of years I have been familiar with the observation that the quality of programmers is a decreasing function of the density of go to statements in the programs they produce. More recently I discovered why the use of the go to statement has such disastrous effects, and I became convinced that the go to statement should be abolished from all "higher level" programming languages (i.e. everything except, perhaps, plain machine code). At that time I did not attach too much importance to this discovery; I now submit my considerations for publication because in very recent discussions in which the subject turned up, I have been urged to do so. (Edsger Dijkstra)

Good uses of goto statement

  • Programming in assembler, though you should not have much assembler language in your project.
  • Compilers/generators: These will use goto to create higher-level structures.
  • To over come limitations of the language, but consider changing language: In C you may use goto to implement exception handling. However ensure that you have a clear idea of the structures that you are implementing. Do not use goto in an ad-hoc way.

When goto can seem like a good idea.

goto is easy to understand, how it does it. However the code that you create (beyond the most trivial) is not easy to understand what it does.

My second remark is that our intellectual powers are rather geared to master static relations and that our powers to visualize processes evolving in time are relatively poorly developed. For that reason we should do (as wise programmers aware of our limitations) our utmost to shorten the conceptual gap between the static program and the dynamic process, to make the correspondence between the program (spread out in text space) and the process (spread out in time) as trivial as possible.

That is our attempts to understand a large system, in terms of how it works in a dynamic way, are going to be very limited. However it is possible to view the system in a static way, and thus make it easier for our brains to comprehend. To do this we must let go of a little of the how. We do not seem to have a problem with this in most cases: we care not how print is implemented.

On assembler code and machines

So our CPUs use goto (jmp instructions). So what, unless you are teaching assembler language and CPUs.

But do all CPUs use goto? Possibly not, I am not an expert on this. However here is a discussion on what modern CPUs think of goto/jmp.

That happens when a modern (instruction pipelined cpu), fetches a conditional jump instruction?

All is not well, first it tries to guess which way the branch will go, then it goes that way. If it get it wrong it hits the brakes, backs up and tries again. The circuitry in the x86 for making this guess, is huge. The x86 does not like goto. What about the ARM, its branch prediction circuit is tiny (if it is a branch back, then assume that the branch will be taken, else assume that it will not), The ARM is better at predicting branches than the x86, but how? The arm has more conditional instructions, that is, it has selection built in. This allows it to avoid goto a lot of the time. Its simplistic algorithm then assumes that a jump backward is a loop, and a jump forward is a selection. So though iteration is not explicitly encoded, and selection is only sometimes explicitly encoded. This shows that knowledge of the programs structure is not just a high level thing, it can help the CPU's performance.

The paper cited by @Miles on CAS

As Miles says it showed no benefit of flowcharts. But also not it was year 1977, and they were fortran programmers (goto users). It may be that if the experiment was repeated with the control group using structured programming, that the effect may be negative.

Conclusion

While it will be quicker to teach

10 print "Hello, World"
20 goto 10

than

forever:
    print "Hello, World"

However making the first step easier will make all subsequent steps harder. Someone once said, “Never hire any one that knows basic. They will have been so irreparably damaged by the experience of gotos, that no amount of re-rehabilitation can save them.”, while I do not agree with this statement, there is some truth in it.

Could it be used when teaching for, while, if, etc. As opposed to as a way to program.

Therefore, only teach goto, when teaching assembler language, or at a late stage in high-level programming. However first teach the higher level structures, and make it clear that goto is only a work around for lack of higher-level structures in the language. And consider its use in teaching structured programming.

HOWEVER the article opened a very important question. We need to keep exploring ideas for teaching. Well done @PaulPowell

$\endgroup$
1
$\begingroup$

goto is not bad per se, it depends the way you use it, that's the way Dijkstra and other papers should be read. It can be very useful to simply get out from inner loops without creating weird boolean conditions. Of course if you use it to produce spaghetti code, that is bad.

For example, Java banned goto but gives a break to label statement which is exactly a kind of good goto. On the converse, C lacks of this useful extend break so you need to write thing like:

for (...) {
  for (...) {
      for (...) {
          ....deep inside...
          if (...) goto end;
  }
}
end:

which is much much better than using boolean condition to exit from the loops one-by-one. I doubt anyone would consider such usage as bad, in really helps reading the code which would be much more difficult with a mess of strange combinations of conditions.

Naturally flowcharts illustrate the jumps in between portions of code and this can be simply implemented with jumps. After all an if necessitate a unconditional jump. Beginners have sometimes difficulties to understand what exactly happens in construct like if, while, etc and ask "what code is executed after that", saying that a jump exists from the end of a block to the beginning of another one is a good way to explain, much more than a purely syntactic explanation.

$\endgroup$
2
  • 1
    $\begingroup$ Every control structure in any language can be described as "a kind of goto". $\endgroup$
    – T.E.D.
    Sep 30, 2017 at 17:58
  • $\begingroup$ @T.E.D. Every high-level program is compiled to machine code. The only flow control instructions in machine code, are jump (goto), and jump_to_subroutine (gosub / call, this one is almost structured). The point is not that it gets converted to a goto, the point is that all gotos should be used to implement control structures, and preferably these structures should be baked into the language, and add-hock goto removed from the language. break in a for look is a control structure, but break in a case may not be. You have to make your own structure with case in the C languages. $\endgroup$ Dec 3, 2017 at 15:21
0
$\begingroup$

Flowchart like drawings are a great help when trying to solve problems with multiple cases. A simple example

Exercise: given three numbers a, b and c, print them in ascending order.

The student is expected to articulate a lot of comparisons, and quickly gets lost because his/her brain can't handle 6 cases and the necessary tests at the same time.

So some intermediary representation is needed to work on it. Say, I obviously have to compare things. Let's start with a comparison of a and b. On one side, I know a is bigger. On the other side b is bigger. What else ?

A graphical representation helps to work on the decision tree, much more than a textual representation if embedded if-then-else.

Image of work in progress. 1 of 6 cases solved. Extending the diagram can be done on any order.

enter image description here

Yellow boxes show what I know about the order in some case. c? means : "c could be there".

Question : What is obviously wrong? :-)

$\endgroup$
2
  • $\begingroup$ You have used a flowchart to model a program flow tree, to model a decision tree. Just use a decision tree. This is basically the same as what you have draws, but minor notation change. And more importantly, no suggestion that this is what the program looks like. Imagine writing a program from this flowchart, that can sort 100 items. $\endgroup$ Sep 28, 2017 at 8:47
  • 1
    $\begingroup$ @ctrl-alt-delor sometimes the decision tree grows "indefinitely", and when you remark two situations are similar, comes the idea of jumping back to a previous point. Then you recognize a loop. Or a regular infinite tree, if you are more mathematically inclined. PS: I dont teach a notation for finished programs, but an approach. When you recognize a loop, you know what is the condition, and what you want to repeat. $\endgroup$ Sep 28, 2017 at 8:52
0
$\begingroup$

Here is a generic flowchart of a specific type of control flow:

This control flow cannot be implemented with only control flow structures (if, switch, while, for, do while). You have to either use a goto after one of the conditions, or bend up another structure to simulate it. The latter naturally results in code ranging from slightly weird to awful (loops that don't actually loop, infinite loops with if+break conditions in the middle, artificial flag variables which form some kind of state machine, one-off functions that don't actually represent a stand-alone operation...).

The truth is that control flow structures do not cover all possible cases. goto should always be the last ever tool you try to solve a problem, but you shouldn't throw it away from your toolbox lest you want to end up driving a screw in with a hammer.

$\endgroup$
20
  • $\begingroup$ Good to know your history, of course: en.wikipedia.org/wiki/Structured_program_theorem. You have something nice and tricky, but not essential. $\endgroup$
    – Buffy
    Sep 28, 2017 at 15:33
  • 1
    $\begingroup$ @Buffy I guess nothing is "essential" if you give up on readability. I really like the "Single-while-loop, folk version of the theorem" section from the page you linked, even if it addresses an extreme form of what you have to do with control flags (p is completely artificial, and is only needed because of the shortcomings of the structured flow). I especially like the last quote before the block of code, which neatly sums up my PoV. $\endgroup$
    – Quentin
    Sep 28, 2017 at 15:38
  • $\begingroup$ I worry about "readability". Suppose that your "simple" flowchart results in code that is spread over about 5 pages. Is it still "readable". The history of computing languages seems to imply that go-to should just go. Python, Scala, etc, don't include it and there are other ways to think than with low level structures. These result in cleaner and more maintainable code. One problem with go-to is that it often results in "write-once" or even "write-only" software that is impossible to maintain in the face of changing requirements. $\endgroup$
    – Buffy
    Sep 28, 2017 at 15:45
  • $\begingroup$ For Ruby's support of goto see: patshaughnessy.net/2012/2/29/… $\endgroup$
    – Buffy
    Sep 28, 2017 at 15:46
  • 1
    $\begingroup$ A five-page nested loop won't do you any good either, so that's a job for another structuring tool (namely, functions). Anyway, there's no doubt that structured control flow is a benefit in the overwhelming majority of cases. But wanting, in the tiny number of cases when it isn't enough, to simulate a goto by misusing a control structure is just a bad idea. The tell-tale symptom is the apparition of infinite or do-once loops with breaks, or the proliferation of control flags. That's not "more maintainable" code in the slightest compared to a simple labeled goto. $\endgroup$
    – Quentin
    Sep 28, 2017 at 15:57
0
$\begingroup$

There are a lot of answers here about flowcharts, and the author's answer seems centered around grade-school students (as that is what his article was about).

However, there are in fact some instances where we professionals do use gotos. We don't like to talk about it, because they have such a bad rep. However, if you crack open the code for most of the world's lexical analyzers you will find gotos. Lex itself generates gotos (admittedly, as do many other automated source code generators).

Gotos are in fact the natural expression of a state machine. It is meet and right to try to train students to put more structure into their programs than a simple state machine. However, there are a few tasks that in fact do not have more structure to them than a state machine. A lexical analyzer is one of these tasks.

The typical goto-less method to work around this is to create a variable to hold the state, and write a big honking switch statement embedded in a loop with little or no code between them. That works, and avoids using the g-word, but it doesn't really gain anything. Rather it just hides the unstructured control flow under an artificial layer of structure.

(Note: gotos are also commonly used in languages that don't have exception handling, but that's arguably a separate issue).

The only tweak I'd make to traditional anti-goto training would be to say that if I ever see something like this in your code:

for (;;) {
    switch (state) {
       // multiple screens of code here
    }
}

Then one of two things are going to happen: Either there was a properly structured way to write the same code, and I'm going to grade you just like you wrote "goto" there, or there isn't, and I might dock you a point or two for the extra obfuscating of not using goto.

Also, courses like Compiler Construction that naturally entail gotos should mention this issue, and not hide from it.

$\endgroup$
8
  • 1
    $\begingroup$ Generated programs are a radically different beast from code that humans maintain. Most (I hesitate to say all, but I can't think of a counterexample) state machines I've written in the real world are better written out with an explicit state; conflating program state with program counter location, the way you have to do it if you rely on goto for state change, would have made them very hard to maintain, because the states are not clearly disjoint. Admittedly, goto might be the easiest way to express a state machine which is a toy exercise, designed to keep the states simple. $\endgroup$ Sep 29, 2017 at 20:51
  • $\begingroup$ @Gilles - There are of course good ways and bad ways to organize state-machine goto code (believe it or not), just like any other kind of code. But you aren't "fixing" that by artificially imposing an unnecessary loop-switch structure on top of it. $\endgroup$
    – T.E.D.
    Sep 29, 2017 at 21:23
  • 1
    $\begingroup$ My point is that the state machines I usually see are a loop around something that contains a switch, or at least a bunch of conditionals. The loop body is hardly ever just a switch. It tends to be something like: read and parse a message, run consistency checks, analyze the state, update some data structures, emit a log message, make a state transition, loop. That's hard to express with goto statements, even in the best of cases where “analyze the system state” only comes up once. $\endgroup$ Sep 29, 2017 at 21:37
  • $\begingroup$ @Gilles - If there's really a significant amount of "always run" code, yes that's a good reason for a loop. However, I tried that for a while with my first serious manual lexer, and gave it up. The problem is that stuff outside the switch tends to end up only running at the end or beginning of most loops, not all of them (practical example: don't bother updating the lexeme in comment state.) After about the 3rd interlocking exception, you end up just making that stuff subroutines and calling them at the end of the states that need it. That's much easier to follow code. $\endgroup$
    – T.E.D.
    Sep 29, 2017 at 22:24
  • $\begingroup$ @T.E.D. Create/Use a meta compiler (a compiler compiler). Compilers are allowed to output gotos. Any domain specific language should be well structured, but may output code that is not intended to be maintained my humans. Every other compiler outputs JMP instructions. $\endgroup$ Oct 13, 2017 at 13:00
0
$\begingroup$

Three quick answers:

  • flowcharts are useful to communicate and document the logic of a process. Not knowing how they work may well be a problem in some kinds of work.

  • goto has value in many situations where some programmers (not all) will work. Not everything is done in high level or modern languages. At a low level on most processors there are no loops, only conditional and unconditional gotos (branches). Older non structured languages also remain in use.

  • goto also has considerable importance in security/vulnerability. That's because hacking and vulnerability work (and therefore security) can involve understanding stack manipulation techniques and disassembly (machine code to assembler) which are completely based on jumps not loops. If you look at an infosec analysis of malware you'll see the need to comprehend code that doesn't have high level classes and objects.

$\endgroup$
6
  • $\begingroup$ I can't tell what "[hacking... is] completely based on jumps not loops" is trying to get at. I would suggest removing your third bullet point, or trying to provide evidence for it. That doesn't match my experience of security. Are you perhaps trying to hint at ROP attacks? But that's something entirely different; ROP has to do with CALL/RET instructions, and I don't see what the difference between jumps vs loops has to do with it. $\endgroup$
    – D.W.
    Sep 28, 2017 at 17:43
  • $\begingroup$ Anyone analysing malware, or looking at vulnerability testing that requires analysis of compiles software, will need to dip into assembler. Which means understanding assembler, CPU address (+other) stacks (and perhaps interrupts) and so on. Which means understanding code that exclusively uses jumps and branches, such as JMP/JEQ/JL/JNE (or whatever the equivalent is on your CPU/SCAD). AKA understanding goto. Crucial for infosec work. $\endgroup$
    – Stilez
    Sep 28, 2017 at 18:16
  • $\begingroup$ That's an argument for eventually teaching students assembly language, at least if they want to do infosec reverse engeering. That's not the same as an argument for teaching goto. And it has nothing to do with "jumps vs loops". $\endgroup$
    – D.W.
    Sep 28, 2017 at 22:08
  • $\begingroup$ @D.W. I think that by “goto also has considerable importance in security/vulnerability”, Stilez means “goto is important to write native exploits”. Which is true, as part of the more general fact that writing native exploits requires a very good understanding of how a machine executes a program. But teaching how to write exploits is not relevant to the context of the question, which is teaching to fairly novice students (the author of the article seems to insist that it's especially relevant for middle school students). $\endgroup$ Sep 29, 2017 at 21:41
  • $\begingroup$ By the way, the statement “at a low level there are no loops, only conditional and unconditional gotos” is partly wrong (some processors do more than that for you, e.g. they manipulate the stack, and conversely a jump can actually be more than a goto if it involves changing processor modes). It's also misleading, because even in microcontroller programming, very little code is written in assembly and goto is rarely used in C, let alone higher-level languages. $\endgroup$ Sep 29, 2017 at 21:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.