[History] An editor letter by Edsger Dijkstra, titled: "go to statements considered harmful" (march 1968). (dl.acm.org)
from abbadon420@lemm.ee to programming@programming.dev on 19 May 2024 19:17
https://lemm.ee/post/32376299

In this letter, Dijkstra talks about readability and maintainability in a time where those topics were rarely talked about (1968). This letter was one of the main causes why modern programmers don’t have to trouble themselves with goto statements. Older languages like Java and C# still have a (discouraged) goto statement, because they (mindlessly) copied it from C, which (mindlessly) copied it from Assembly, but more modern languages like Swift and Kotlin don’t even have a goto statement anymore.

#programming

threaded - newest

stepan@lemmy.cafe on 19 May 2024 20:16 next collapse

TIL that C# and Java have a goto statement.

leftzero@lemmynsfw.com on 19 May 2024 20:25 next collapse

Forget about goto, the latest version of C# introduced what’s essentially comefrom.

airbreather@lemmy.world on 19 May 2024 21:54 next collapse

To be fair, await is a bit more like comefrom, and it’s been around for a few releases now.

asyncrosaurus@programming.dev on 20 May 2024 15:36 next collapse

async/await was introduced in version 4.5, released 2012. More than a few releases at this point!

BatmanAoD@programming.dev on 22 May 2024 21:49 collapse

How is await like comefrom, any more than threading is like comefrom? The variable context is preserved and you have no control over what is executed before the await returns.

NaoPb@eviltoast.org on 21 May 2024 08:33 next collapse

Please don’t link to medium articles. That page is terrible to visit.

leftzero@lemmynsfw.com on 21 May 2024 08:47 collapse

Looks fine on Firefox on Android with uBlock Origin. 🤷‍♂️

NaoPb@eviltoast.org on 21 May 2024 09:15 collapse

I’m running exactly the same and it doesn’t look fine on my end.

leftzero@lemmynsfw.com on 21 May 2024 09:22 collapse

Huh. Maybe it’s NoScript, then.

NaoPb@eviltoast.org on 21 May 2024 09:25 collapse

Could be. I’m getting forced to make an account and such. That’s why I hate medium.

BatmanAoD@programming.dev on 22 May 2024 21:50 collapse

What…? That is a terrible idea.

leftzero@lemmynsfw.com on 22 May 2024 21:56 collapse

It’s scary as fuck, yeah, but, to be fair, it’s only intended to be used by code generators, and it’s quite awkward to use outside of them.

TehPers@beehaw.org on 20 May 2024 00:08 next collapse

In C# at least, goto can take you between case labels in a switch statement (rather than using fallthrough), which I don’t view as being nearly as bad. For example, you can do goto case 1 or goto default to jump to another case.

The only other use of goto I find remotely tolerable is when paired with a labelled loop statement (like putting a label right before a for loop), but honestly Rust handles that far better with labelled loops (and labelled block expressions).

asyncrosaurus@programming.dev on 20 May 2024 15:43 collapse

I’ve programmed C# for nearly 15 years, and have used goto twice . Once to simplify an early break from a nested loop, essentially a nested continue. The second was to refactor a giant switch statement in a parser, essentially removing convoluted while loops, and just did a goto the start.

It’s one of those things that almost should never be used, but the times it’s been needed, it removed a lot of silliness.

atzanteol@sh.itjust.works on 20 May 2024 12:14 collapse

Java doesn’t. Well, it’s a reserved keyword but it’s not implemented.

Carighan@lemmy.world on 21 May 2024 16:19 collapse

Yeah but we got labels with continue and break, so we can pseudo goto.

atzanteol@sh.itjust.works on 21 May 2024 17:09 collapse

Following that logic if, else and while are also “pseudo goto” statements.

There’s nothing wrong with conditional jumps - we couldn’t program without them. The problem with goto specifically is that you can goto “anywhere”.

lmaydev@lemmy.world on 20 Jul 2024 15:14 collapse

If pretty much gets compiled to a goto statement. Well more a jumpif but same principle

tedu on 19 May 2024 21:04 next collapse

Languages don't have goto because they mindlessly copied it.

huginn@feddit.it on 19 May 2024 22:53 collapse

True it wasn’t mindless - just idiotic

atzanteol@sh.itjust.works on 20 May 2024 14:07 collapse

It’s not idiotic. You can do a lot of performance optimizations with GOTO so providing it as a “use it if you know what you’re doing” option is fine. And some things are easier to read with GOTO.

FWIW the Linux source code is full of GOTO statements. Nearly 200,000 of them in fact.

huginn@feddit.it on 20 May 2024 15:01 collapse

There’s a solid reason for goto in C.

Bringing goto into Java was (and is) idiotic.

If you’re trying to squeeze every ounce of performance out of your code then you’ll need those optimizations.

But any higher level language than C the entire point is to write easily maintainable and useful code that any idiot can go, read and update. A goto is antithetical to readability.

ggppjj@lemmy.world on 20 May 2024 22:56 collapse

It can be, sure. But when used in a limited manner where it makes sense it can be the more readable option. I’ve used it in a try/catch to retry the operation after changing a variable. One label (“reconnect”), one goto, totally easy to understand on a surface level.

Naich@lemmings.world on 19 May 2024 22:04 next collapse

switch statements are three gotos in a trenchcoat.

TehPers@beehaw.org on 20 May 2024 00:19 next collapse

Duff’s device takes this to a whole new level.

abbadon420@lemm.ee on 20 May 2024 06:13 next collapse

This is very nice and clean

wewbull@feddit.uk on 20 May 2024 08:40 collapse

Egads! My eyes.

I’d rather it was just written in assembly. It’s the do { opening a block under the case 0, but then proceeding to have further case statements inside that block. You now have case statements in two different scopes that are part of the same switch.

magic_lobster_party@kbin.run on 20 May 2024 06:40 collapse

Anything is a goto in disguise when you think about it

wewbull@feddit.uk on 20 May 2024 08:33 collapse

In most CPU instruction sets, the only conditional instruction is branch (aka goto).

magic_lobster_party@kbin.run on 20 May 2024 10:41 collapse

And after each instruction, the CPU go to the next instruction

Deebster@programming.dev on 20 May 2024 01:40 next collapse

For such an influential letter, I don’t find his arguement all that compelling. I agree that not using go to will often lead to better structured (and more maintainable) programs, but I don’t find his metric of “indexable process progress” to satisfyingly explain why that is.

Perhaps it’s because at that time people would be running the programs in their heads before submitting them for processing, so they tended to use more of a computer scientist mindset - whereas now we’re more likely to use test cases to convince ourselves that code is correct.

Kissaki@programming.dev on 20 May 2024 07:25 next collapse

I think it’s convoluted way to describe it. Very technically-practical. I agree it’s probably because of historical context.

The argument I read out of it is that using goto breaks you being able to read and follow the code logic/run-logic. Which I agree with.

Functions are similar jumps, but with the inclusion of a call stack, you can traverse and follow them.

I think we could add a goto stack / include goto jumps in the call stack though? It’s not named though, so the stack is an index you only understand when you look at the code lines and match goto targets.

I disagree with unit tests replacing readability. Being able to read and follow code is central to maintainability, to readability and debug-ability. Those are still central to development and maintenance even if you make use of unit tests.

Deebster@programming.dev on 20 May 2024 08:04 collapse

I wasn’t saying that unit tests replaces readability, I was saying that back in the 60s they’d reason and debug using their brains (and maybe pen and paper), with more use of things like formal proofs for correctness. Now that we write more complicated programs in more powerful environments, it’s rare to do this (we’d use breakpoints, unit tests, fuzzing, etc).

atzanteol@sh.itjust.works on 20 May 2024 13:53 collapse

Perhaps it’s because at that time people would be running the programs in their heads before submitting them for processing, so they tended to use more of a computer scientist mindset - whereas now we’re more likely to use test cases to convince ourselves that code is correct.

This is 1968. You didn’t have an IDE or debugger. Your editor was likely pretty terrible too (if you had one). You may have still been using punch cards. It’s possible the only output you got from your program was printed on green-bar paper.

“Back in the day” it wasn’t uncommon to sit with a printout of your code and manually walk though it keeping state with a pencil. Being able to keep track of things in your head was very important.

GOTO existed in part for performance purposes. When your CPU clock is measured in megahertz, your RAM is measured in kilobytes and your compilers don’t do function in-lining it’s quicker and cheaper to just move the program pointer than it is to push a bunch of variables on a stack and jump to another location, then pop things off the stack when you’re done (especially if you’re calling your function inside a loop). Even when I was programming back in the '80s there was a sense that “function calls can be expensive”. It wasn’t uncommon then to manually un-roll loops or in-line code. Compilers are much more sophisticated today and CPUs are so much faster that 99% of the time you don’t need to think about now.

Oddly enough the arguments against GOTO are less important today as we have much better development tools available to us. Though I certainly won’t recommend it over better flow-control structures.

0x0@programming.dev on 21 May 2024 08:16 collapse

When your CPU clock is measured in megahertz, your RAM is measured in kilobytes

Ah yes, the good ol’ days when developers programmed for efficiency.

atzanteol@sh.itjust.works on 21 May 2024 17:46 collapse

Mostly because they had to. Writing efficient code and easy-to-read code are often at odds with each other. I like being able to create lots of functions that can be called from a loop without needing to worry too much about function call overhead. I can prioritize readability for some time before I ever need to worry about performance.

0x0@programming.dev on 21 May 2024 18:25 collapse

I get that but it seems as though no one cares at all about efficiency these days.

atzanteol@sh.itjust.works on 22 May 2024 00:21 next collapse

People have been complaining about this exact thing forever. Even back when “people cared about efficiency”.

BatmanAoD@programming.dev on 22 May 2024 21:44 collapse

Does the catchphrase “blazing fast” ring any bells? Some people care.

(Arguably that’s just the pendulum swinging the other way; Ruby, Python, and Java ruled the software world for a while, and I think that’s a large part of why the Go and Rust communities make such a big deal about speed.)

Kissaki@programming.dev on 20 May 2024 06:53 next collapse

Go has goto too. They surely did not “mindlessly copy” it.

The standard library makes use of it. So they most definitely see a warranted use-case for it.

OP argument against using it in high level languages may still hold though. Go may have introduced it as a systems language which allows control over alternative implementations.

abbadon420@lemm.ee on 20 May 2024 07:20 collapse

The article does say that there are good cases to use goto, but they are rare and most programmers won’t ever encounter such situations. I believe the jist is that it can do nore harm than good.

eveninghere@beehaw.org on 20 May 2024 06:57 next collapse

For C it makes sense. The point of C is that it can work as a low level language. Basically, everything doable with assembly SHOULD be doable with C, and that’s why we don’t need another low level language that’s basically C with goto.

Even though almost all of C users should never use goto.

realharo@lemm.ee on 20 May 2024 08:40 collapse

C is one of the few languages where using goto makes sense as a poor man’s local error/cleanup handler.

42yeah@lemm.ee on 23 May 2024 01:31 collapse

Yeah. Without a proper error handling mechanism, goto is actually useful for once.

pkill@programming.dev on 23 May 2024 09:02 collapse

Still don’t get why Go simultaneously picked this and introduced defer

Kissaki@programming.dev on 20 May 2024 07:01 next collapse

PDF magic… It has grainy text. But the selectable text and displayed text have a 1-character offset.

I assume they display the original scan so it definitely does not contain errors, while still providing the image-parsed text for searchability, indexability, and select-+copyability?

<img alt="screenshot of text + backing text offset" src="https://programming.dev/pictrs/image/784e817f-90b5-4815-9427-e0a68fbe812b.png">

Unfortunately, the grainy text is hard[er] to read.

Kissaki@programming.dev on 20 May 2024 07:20 next collapse

Their main argumentation (from page 1) summarized:

You know the state and progress of a program from the line you are on. A goto breaks that.

You can index the progress of a program through static line indexes and a dynamic loop index and function call stack. A goto breaks that. Including a “statements/lines since beginning of execution” is infeasible for understanding.

0x0@programming.dev on 20 May 2024 08:30 next collapse

goto does have some uses, such as single exit point, but should be used sparingly.

billybong@lemmynsfw.com on 20 May 2024 21:26 collapse

Single exit point is an assembly rule that was mindlessly ported to C/C++. It doesn’t make sense in a structured language.

0x0@programming.dev on 21 May 2024 08:03 collapse

Maybe for your use-cases, for mine i find it quite useful.

Acters@lemmy.world on 22 May 2024 03:04 collapse

I’ll be very interested to hear more, do you have a blog?

0x0@programming.dev on 22 May 2024 08:44 collapse

A common case is a function that uses resources like opening files, sockets, whatever. If there’s an error you want to ensure a clean exit, so at different parts of said function you goto the end where you check if said resources are being used and release them before exiting.

Cleaner than constantly checking at every error.

atzanteol@sh.itjust.works on 20 May 2024 12:12 collapse

Java does not support goto.

lemmyvore@feddit.nl on 20 May 2024 19:27 next collapse

Well it has labeled breaks but that’s the closest it gets to it.

mrkite@programming.dev on 20 May 2024 22:14 collapse

And yet it’s still easy to write spaghetti code in Java. Just abuse inheritance. Where is this function implemented? No one knows but the compiler!

0x0@programming.dev on 21 May 2024 08:14 next collapse

You mean SpaghettiFactory()

SatouKazuma@ani.social on 21 May 2024 15:09 next collapse

And don’t forget to use miracle sort for any sorting needs you have. Why do the work yourself when you can just hope it gets solved for you?!

warlaan@lemm.ee on 22 May 2024 08:01 collapse

That doesn’t make it spaghetti code though. In well-written OOP code you shouldn’t care where a function is implemented. The problem is a much too high level of abstraction. If your high level code is so abstract that it is only running tasks and handling messages there’s no way to write it in a way that prevents mistakes because you couldn’t possibly know what the actual implementations do.