Live data from Hacker News

GOTOphobia considered harmful in C

blog.joren.ga

171–180 of 319 posts

Re: GOTOphobia considered harmful in C

#171
post #26

> On the other hand, today we have the very opposite situation: programmers not using goto when it's appropriate and abusing other constructs, what ironically makes code only less readable. One I see all the time from beginners is creating a finite state machine using one method per state and jumping between states by calling the next state’s method from within the current state’s method. Essentially just emulating g…

This is one of those problems that Tail Call Elimination cleanly addresses. The "obvious" approach to writing an FSM does exactly what you'd expect.

Gotos are great approach for writing a Flying Spaghetti Monster!

Re: GOTOphobia considered harmful in C

#172
post #140
post #77

Earlier quoted context omitted.

The thing is that many people today have never encountered the sort of spaghetti code that Dijkstra was talking about in 1968. There's plenty of confusing and messy code around, but true spaghetti code that GOTOs all over the place and is nigh-impossible to follow has been extremely rare for a long time. I can't recall encountering it in the last 30 years. It easy to misunderstand what he was even talking about becau…

To give people some kind of an idea of what it was created in response to: Imagine writing an entire program in one single main function. The only thing you're allowed to do for flow control is goto. You can do 'goto somelabel;' for an unconditional goto, or you can do 'if (somecondition) goto somelabel;' for a conditional goto. Here's some examples of how it would look if if translated to something C-like: Loops wou…

tangentially, can somebody point me to what are considered the best fizzbuzz solutions? I'm both an experienced and cs-educated coder, and I know what I would consider to be a good solution, but I have no idea what the rest of "you" are looking for. (my favored solution would be a small number of state machines running in parallel to sieve-of-eratosthenes the correct answers thus avoid innumerable divisions, but maybe that's just me and I'm old fashioned?)

Re: GOTOphobia considered harmful in C

#173

Earlier quoted context omitted.

Early Fortran already had loops, but with labels: INTEGER A(4,4), C, R ... DO 10 WHILE ( C .NE. R ) A(C,R) = A(C,R) + 1 C = C+1 10 CONTINUE Note that Fortran has evolved significantly over time. This is how you would write the same in Fortran 77: INTEGER A(4,4), C, R ... C = 4 R = 1 DO WHILE ( C .GT. R ) A(C,R) = 1 C = C - 1 END DO

Those are just regular loops, though, right? I’m looking for the posttest loop, sometimes known as the do…while or until loop. There seems to be a unfortunate inconsistency in the naming of this thing.

Ah, right, I misread your post. DO WHILE is indeed a "normal" while loop. There doesn't seem to be an equivalent to "do { ... } while", as found in most C-style languages.

> There seems to be a unfortunate inconsistency in the naming of this thing.

Well, Fortran is older than C, so you cannot really blame them :-)

Re: GOTOphobia considered harmful in C

#174

In RAII languages[0], you obviously don't need unrestricted gotos. However, I always find myself missing it when writing nested loops. Labeled break and continue[1] ought to be considered standard structure programming primitives. These are restricted gotos and allowing them to break or continue a parent loop doesn't unrestrict them much. But it does significantly improve the expressive power of your looping construc…

> Labeled break and continue ... I find that normally if I need nested break then it suffices to refactor the target loop into a function and use return instead. I don't think I normally miss multilevel continue, but the same strategy would work for that too. You'd just pull out the target loop body rather than the whole loop. If that doesn't work because you need to select too many different break/continue levels (m…

> You'd just pull out the target loop body rather than the whole loop.

that's a "good solution" in the sense of "lambda is the ultimate goto", but if you're writing a loop over the rows and columns (or more dimensions) of something, pulling out and segregating the control structure for the innermost (and potentially other) layers of the hierarchy can make a simple depth first exploration look obscure. If the total amount of code is fitting in a screenful, I'd rather put multi-level break or continue labels and then goto them sparingly.

Re: GOTOphobia considered harmful in C

#175
post #73

Earlier quoted context omitted.

Yes. There's a reason pretty much every secure C coding standard dictates exact what I said, like CERT C etc. There's a reason they have weird bugs. Just because it's an impressive piece of software, doesn't mean it can't have horrible design pattern written by substandard coders. And in an open source project with as many contributors as Linux, I would say it's not hard to fathom that there's a significant number of…

or maybe its that things like a kernel reasonably need to use goto? or at least at the time it was written, there werent alternatives that were performant enough.

a more interesting discussion between your point and his would be to show simple examples where each of the views break down. When you're dealing with allocation or handle cleanup, SESE sounds good to me. But with multilevel loop break or continues, even observing SESE I can see room for more gotos. But I don't know what either you or he are talking about.

Re: GOTOphobia considered harmful in C

#176
post #130
post #66

Earlier quoted context omitted.

IMO this is a design bug in C++. The authors couldn't agree on what to do in the exception-during-unwind scenario, so they chose the worst possible option: crash. In most cases, an second exception raised while another exception is already being thrown is merely a side-effect of the first exception, and can probably safely be ignored. If the idea of throwing away a secondary exception makes you uncomfortable, then an…

Even if the standard consolidated on one way or another to pack up secondary exceptions (or discard them) how likely is the calling code going to be able to handle and recover from this case? I am personally on team crash - I would rather my program exited and restarts in a known state then being in some weird and hard to replicate configuration.

So, I personally prefer to use exceptions for "panic" scenarios, like assertion failures, where the application has hit a state it doesn't expect and cannot handle.

Crashing makes sense in these scenarios if the application is only doing one thing. But I am usually working on multi-user servers. I would rather fail out the current request, but allow concurrent requests from other clients to continue.

Yes, I understand the argument: "But if something unexpected happened, your application could be left in a bad state that causes other requests to fail too. It's better to crash and come back clean."

This is not my experience in practice. In my experience, bad states that actually poison the application for other requests are extraordinarily rare. The vast, vast majority of exceptions only affect the current request and failing out that request is all that is necessary. Taking down the whole process is not remotely worth it.

Moreover, crashing on assertions has the unintended consequence of making programmers afraid to write assertions. In a past life, when I worked on C++ servers at Google, assertion failures would crash the process. In this argument, I saw some people argue that you should not use assertions in your code at all! Some argued for writing checks that would log an error and then return some sort of reasonable default that would allow the program to continue. In my opinion, this is an awful place to end up. Liberal use of asserts makes code better by catching problems, making the developer aware of them, and avoiding producing garbage output when something goes wrong.

Re: GOTOphobia considered harmful in C

#177
post #50

I always encourage people to go read Dijkstra's GOTO paper, instead of just its title. It's a short and easy read, almost like a blog post. If you pay attention, you can see that the he was talking about spaghetti code vs structured code. It's better when the lexical structure of the source code maps to the execution structure. That is, if you know what is the current line being executed, you have a good idea of what…

> It's better when the lexical structure of the source code maps to the execution structure.

Sure, but that has nothing to do with whether the GOTO statement should be used. The semantics of GOTO are arguably quite clear; they amount to setting a different continuation for the running program. (Semantically, this implies that the precondition of the GOTO statement is made a possible precondition for the label that the statement jumps to; and execution simply does not proceed to the next statement.)

There are even "relooper" algorithms to reconstruct a structured program from patterns in the idiomatic use of GOTO statements: they are used in compiling to structured object languages such as WASM code. Using GOTOs in an idiomatically sensible way (avoiding spaghetti code) may be less readable than writing actual structured blocks, but only slightly so.

Re: GOTOphobia considered harmful in C

#179
post #86
post #77

Earlier quoted context omitted.

The thing is that many people today have never encountered the sort of spaghetti code that Dijkstra was talking about in 1968. There's plenty of confusing and messy code around, but true spaghetti code that GOTOs all over the place and is nigh-impossible to follow has been extremely rare for a long time. I can't recall encountering it in the last 30 years. It easy to misunderstand what he was even talking about becau…

This. To find an example, I did a search for “Commodore PET Basic programs”. Here’s a book from 1979 that shows what spaghetti code looks like, in my opinion: http://www.1000bit.it/support/manuali/commodore/32_BASIC_Pro... The first program listing is on page 24 of the PDF. Try to follow the logic of the program. Why does line 400 go to 280? What paths can lead to line 400? Who knows! And this is high-quality BASIC b…

> The first program listing is on page 24 of the PDF. Try to follow the logic of the program. Why does line 400 go to 280? What paths can lead to line 400? Who knows!

Without looking at the post-program material, this isn't exactly a difficult question to answer.

Line 400 is preceded by some print statements:

    370    PRINT "PRESS 'E' TO END, SPACE TO CONTINUE"
    380    GET R$:IF R$="" THEN [goto] 380
    390    IF R$="E" THEN [goto] 120
    400    L=0:GOTO 280
So we have a prompt that says "press E to end, space to continue", and then branches one of three ways: if you provide no input, the prompt is shown again; if you provide an E, the entire program restarts from scratch, and if you do anything other than that, the count of lines drawn on screen is reset to 0 and the next 18 lines of the chart are drawn.

We can assume that line 400 will be hit whenever a piece of chart is drawn to the screen.

The program's structure here is a nested loop: there is a loop between lines 280 and 400 (displaying the chart indefinitely, 18 lines at a time) containing another loop between lines 300 and 360 (displaying 18 lines of a chart, one line at a time).

Why is this supposed to be an example of spaghetti code?

Re: GOTOphobia considered harmful in C

#180

Exceptions are GOTO's. Sure, it's more likely to be safe in terms of memory/resource leaks, but in terms of program logic it is no different.

Returns are also gotos then.

Not in the Dijkstra "Go to statement considered harmful" sense. Nor are the goto keywords found in most modern languages. These retain structure and thus are not considered harmful.

But there is a good case to be made that exception handlers are gotos in the Dijkstra sense, at least when used for anything other than exceptions, like passing errors around.

Post reply on HN