Live data from Hacker News

Goto (2007)

beej.us

191–200 of 207 posts

Re: Goto (2007)

#191

Probably coming too late to the discussion, but commenting anyway... The issue I think is that people today read "GOTO Considered Harmful" without really understanding the world at the time. Other than simple integer FOR loops, basically all control-flow in the FORTRAN of those days was accomplished with GOTO -- and to numbered lines, not labels. Things we take for granted in all languages today like { code blocks }…

This is my pet peeve with how they teach kids programming. Granted, I only have anecdata on that topic, gleaned from how they teach my own kid at school, but I still can't shake the feeling that we're doing them a disservice by making them skip straight to JavaScript or Python. I wonder what it would be like if kids started with BASIC. And not Visual Basic or any other modern, structured flavor. No, I mean the ancien…

I teach high school CS and have eventually come to the same insight, and found that novice programmers do indeed understand primitive BASIC much more easily than Python. Python seems simple to us, but there is so much abstraction even in its base-level syntax. I am gradually redeveloping my course materials to use BASIC (via replit.com) in the early stages.

Re: Goto (2007)

#192

Probably coming too late to the discussion, but commenting anyway... The issue I think is that people today read "GOTO Considered Harmful" without really understanding the world at the time. Other than simple integer FOR loops, basically all control-flow in the FORTRAN of those days was accomplished with GOTO -- and to numbered lines, not labels. Things we take for granted in all languages today like { code blocks }…

Can you give an example of where you've used goto in C or a C-like language? Or a rough estimate of the number of times you've found goto to be the best solution? I agree with your post in principle, but in practice I can't think of a single example where I've used a goto that wasn't eventually refactored to something better that didn't have the goto. Edit: Probably the most common example (and one given early in the…

The times I found I used the goto statements are retrials.

For example, if a file is locked for writing, I want to wait for 5, then 10, then 15 seconds, retrying each time, before giving up.

In such case I do not want the retrials loop to be my main control structure.

Instead, I jump from inside the IO exception catch block to the ReTry label, restarting the whole operation.

This makes the flow fairly clean.

Re: Goto (2007)

#193
I put 2007 above because the book it's from seems to be from then.

Beej’s Guide to C Programming [pdf] - https://news.ycombinator.com/item?id=26911399 - April 2021 (171 comments)

Beej's Guide to C Programming - https://news.ycombinator.com/item?id=26100391 - Feb 2021 (1 comment)

Beej's Guide to C Programming (2007) - https://news.ycombinator.com/item?id=15198093 - Sept 2017 (79 comments)

Beej's Guide to C Programming - https://news.ycombinator.com/item?id=8295024 - Sept 2014 (1 comment)

Re: Goto (2007)

#194

Earlier quoted context omitted.

Can you give an example of where you've used goto in C or a C-like language? Or a rough estimate of the number of times you've found goto to be the best solution? I agree with your post in principle, but in practice I can't think of a single example where I've used a goto that wasn't eventually refactored to something better that didn't have the goto. Edit: Probably the most common example (and one given early in the…

> deeply nested loops. [...] I will prefer to hide one or more of the inner loops inside of a function call. And I would too... but sometimes there are too many local variables involved to do that cleanly. And, ultimately, if you are making your code less clean to avoid using a goto then you avoided unwisely. > Can you give an example of where you've used goto in C or a C-like language? Well there have been several f…

I really like this answer, but I do think a flag “cleanup_required” could be a clean way to express the code as well, with “if cleanup_required …” after the switch block.

But yep, I have no complaints with the code as presented.

Re: Goto (2007)

#195

Probably coming too late to the discussion, but commenting anyway... The issue I think is that people today read "GOTO Considered Harmful" without really understanding the world at the time. Other than simple integer FOR loops, basically all control-flow in the FORTRAN of those days was accomplished with GOTO -- and to numbered lines, not labels. Things we take for granted in all languages today like { code blocks }…

Can you give an example of where you've used goto in C or a C-like language? Or a rough estimate of the number of times you've found goto to be the best solution? I agree with your post in principle, but in practice I can't think of a single example where I've used a goto that wasn't eventually refactored to something better that didn't have the goto. Edit: Probably the most common example (and one given early in the…

The Linux kernel has 28 million lines of C code, and 180 thousand goto statements.

1 every 160 lines is a goto, and that's just a naive count so includes all header and preprocessor gunk, whitespace, some generated C code, comments, etc.

If you're talking about more pure lines if C, it would probably be close to 1% of statements are goto.

It might not be everyone's cup of tea as the pinnacle of C programming, but it's a real highly used medium-large project that has coped well with a pretty high rate of change from a very wide spectrum of contributors. So it is a good real world example of open C code you can look at that is maintainable while making a lot of use of goto.

Re: Goto (2007)

#196

Probably coming too late to the discussion, but commenting anyway... The issue I think is that people today read "GOTO Considered Harmful" without really understanding the world at the time. Other than simple integer FOR loops, basically all control-flow in the FORTRAN of those days was accomplished with GOTO -- and to numbered lines, not labels. Things we take for granted in all languages today like { code blocks }…

Can you give an example of where you've used goto in C or a C-like language? Or a rough estimate of the number of times you've found goto to be the best solution? I agree with your post in principle, but in practice I can't think of a single example where I've used a goto that wasn't eventually refactored to something better that didn't have the goto. Edit: Probably the most common example (and one given early in the…

There are a few decent examples given by the Linus kernel devs on a LKML thread where an unfortunate soul wandered in and suggested that they refactor to get rid of GOTOs: https://lkml.org/lkml/2003/1/12/126

> "I will prefer to hide one or more of the inner loops inside of a function call."

That risks the additional unnecessary overhead of a function call, which can be expensive in a loop, and not all compilers are as good at optimizing as they should be.

Re: Goto (2007)

#197

Earlier quoted context omitted.

> using SHA-1 as a non-secure hash, That I actually partly disagree with. There are much, MUCH better performing (faster, less memory use, etc) hashes than SHA1 if you don't need security. If you don't need security, and you don't need performance, and you don't have anything else available in libraries, then SHA1 is fine. But that's a pretty rare situation. SHA1 might not be a sign of insecurity, but it's often a si…

On modern Intel/AMD and ARM CPUs, which have SHA-1 instructions, SHA-1 is very fast, faster than many apparently simpler hashes. There are no other so fast hashes with an output of at least 128 bits that you can find in available libraries and use immediately in your code. The only alternative that is faster and long enough is to use an 128-bit polynomial hash like Poly1305 or the one used inside AES-GCM. Such polyno…

> BLAKE3 can be much faster than SHA-1, but only when it is computed in parallel with a large number of cores.

SIMD optimizations are arguably more important than multithreading. Take a look at these SUPERCOP benchmarks on a recent Intel CPU: https://bench.cr.yp.to/results-hash.html#amd64-pascalinspiro.... Those are all single-threaded measurements, and the SHA-1 implementation there is hardware-accelerated, but BLAKE3 is still almost 4x faster. That speedup comes from AVX-512 vector operations, which serial hashes like SHA-1 can't take (as much) advantage of. Not every caller will want to use the AVX-512 implementation (see "downclocking"), but even with AVX2 BLAKE3 would still be faster.

Multithreading is a nice option to have, and of course it looks great in benchmarks if the input is long enough. But general-purpose library APIs like `blake3::hash()` in Rust don't do multithreading by default. They only use SIMD optimizations by default.

Re: Goto (2007)

#198

Goto is a useful precursor for writing a tail recursive solution. For instance, say we have a state machine for recognizing that the last four button presses were 1234. int keypad() // returns 1 if correct key is entered, otherwise loops forever { keypad: switch (getkey()) { case 1: goto got_1; default: goto keypad; } got_1: switch (getkey()) { case 2: goto got_2; case 1: goto got_1; default: goto keypad; } got_2: sw…

I think the better way to create a state machine would use another switch instead of the top-level goto like:

  int keypad()
  {
    int state = 0; // 0 = start, 1 = seen '1', 2 = seen '12', 3 = seen '123'
    while (true) {
      int key = getkey();
      switch (state) {
      case 0:
        switch (key) {
        case 1:
          state = 1;
        default:
          state = 0;
        }
        break;
      }
      case 1:
        switch (key) {
        case 1:
          state = 1;
        case 2:
          state = 2;
        default:
          state = 0;
        }
        break;
      }
      case 2:
        switch (key) {
        case 3:
          state = 3;
        case 1:
          state = 1;
        default:
          state = 0;
        }
        break;
      }
      case 3:
        switch (key) {
        case 4:
          return 1;
        case 1:
          state = 1;
        default:
          state = 0;
        }
        break;
      }
    }
  }
In my mind that reads more obviously as a state machine than a bunch of gotos and labels (and should function the same assuming I typed it correctly, I haven't run it anywhere). It's easy to see each state and how it flows into other states.

Re: Goto (2007)

#199

Earlier quoted context omitted.

Perhaps that's true when you're writing performance-critical code. For most code, readability trumps micro-optimizations.

In plenty of environments, there's a very limited number of calls you can make before the program fails entirely. For instance, in GW-BASIC, your namesake, the limit is less than 100 calls. There are plenty of real useful production langauges where your stack will run out before 1000 frames of depth. But on the other hand, it's quite reasonable to write a state machine which is expected to make [mb]illions of state t…

Oh you're bringing back memories of childhood.

When I wrote in GW-Basic, I only used gotos. Most of the example code that I had access to used gotos.

I was 11 years old at the time.

> There are plenty of real useful production langauges where your stack will run out before 1000 frames of depth

That wouldn't surprise me in an embedded environment. But if that's the case for a run of the mill general purpose programming language that's running a typical web application, I'd be shocked.

Re: Goto (2007)

#200

Probably coming too late to the discussion, but commenting anyway... The issue I think is that people today read "GOTO Considered Harmful" without really understanding the world at the time. Other than simple integer FOR loops, basically all control-flow in the FORTRAN of those days was accomplished with GOTO -- and to numbered lines, not labels. Things we take for granted in all languages today like { code blocks }…

SNOBOL, the non-numerical computing counterpart to FORTRAN, also uses GOTOs, exclusively.

I still run spitbol. Regardless of its assembly-like control flow, I think the pattern matching beats PCRE, and Lua's implementation of LPeg.

Post reply on HN