News for hackers. Stuff that matters.
Re:Anti-If: The missing patterns (2016) by agateau on Wednesday June 27, 2018 @11:46AM (#17409103)
I have heard this called early-returns. I like to write code this way too. Proponents of one-return-per-function probably write code in languages like C which does not have GC or RAII so having only one exit point makes it easy to ensure all resources allocated by the function have been released.

There are ways to do early returns in C without duplicating resource releasing code though, using gotos (it's one of the few cases where gotos make sense, IMHO). Code looks like this:

  int aFunctionWhichMightFail() {
      int result = FAIL;
      Foo* foo = allocateSomething();
      if (!someFunction(foo)) {
          goto fail;
      }
      moreWork(foo);
      result = SUCCESS;
  fail:
      releaseFoo(foo);
      return result;
  }
The Linux kernel makes heavy use of this.
Re:Anti-If: The missing patterns (2016) by reificator on Wednesday June 27, 2018 @11:54AM (#17409174)
> There are ways to do early returns in C without duplicating resource releasing code though, using gotos (it's one of the few cases where I think gotos make sense).

Gotos like that are fine. Despite the title of the paper I don't think Djikstra's meaning was that gotos should be removed entirely.

Re:Anti-If: The missing patterns (2016) by monocasa on Wednesday June 27, 2018 @12:02PM (#17409261)
Yeah. Dijkstra was talking about not building your whole program out of if and goto, and using functions and for/while/etc. Particularly he's talking about Dartmouth BASIC that didn't have anything else.

Like, imagine the spaghetti lovecraftian horror of a non trivial program that's just if and goto. At the time, there was a particularly vocal camp that essentially made the argument that it shouldn't matter since if/goto is equivalent to what exists in the machine code anyway, and you can technically do all the same things.

Re:Anti-If: The missing patterns (2016) by bitL on Wednesday June 27, 2018 @12:37PM (#17409575)
Keep in mind adopting any strategy beyond if/goto as is in machine code comes with reduced efficiency. So we trade efficiency for readability. Some talented genius might make a super efficient piece of art by restricting to if/goto only, that no other approach could beat performance-wise. I guess anyone who does low-level machine code execution optimization is in that camp most of the time.
Re:Anti-If: The missing patterns (2016) by monocasa on Wednesday June 27, 2018 @12:49PM (#17409697)
Not really. You want structured constructs, even in asm, because they play nicer with the speculation and prefetching hardware. Going nuts and throwing away all of the conventions of higher level languages typically kills your perf.
Re:Anti-If: The missing patterns (2016) by bitL on Wednesday June 27, 2018 @01:17PM (#17409954)
Well, it depends; if you can employ locality of code, cache lines etc. to your advantage it might pay off doing crazy things to optimize the innermost loop and similar. Though as you said, you'd structure whole blocks of functionality more higher-levelish. On some embedded systems it still pays off to modify code during execution, e.g. replacing a constant in innermost instruction by pre-computed value from higher level to avoid memory access penalty.
Re:Anti-If: The missing patterns (2016) by astrobe_ on Wednesday June 27, 2018 @03:20PM (#17410979)
It doesn't make sense to me. the absence of "advanced" control flow constructs is one of the things that define assembly language - only branches and conditional branches, plus sometimes conditional execution of single instructions. Then I don't see how you can claim a non-existing thing can play nicer with speculation and prefetching.
Re:Anti-If: The missing patterns (2016) by monocasa on Wednesday June 27, 2018 @03:33PM (#17411086)
There's a lot of optimization at the microarch level towards the kind of code a compiler emits. Modern chips are designed to run C very well, not arbitrary, technically allowed assembly. You'll hit a lot of perf bottlenecks if you throw weird code/data flow graphs at them.
Re:Anti-If: The missing patterns (2016) by astrobe_ on Friday June 29, 2018 @11:11AM (#17424955)
Well, I'd like to see that. Instruction sets designed with high level languages in mind, sure; but speculation and caches disturbed by code that is not shaped like what a compiler does (which compiler, anyway?), that's doubtful to me.
Re:Anti-If: The missing patterns (2016) by a1369209993 on Wednesday June 27, 2018 @01:00PM (#17409811)
Djikstra's meaning was that gotos should be removed entirely. By replacing them with the high-level control-flow constructs them were being used to implement. If your language doesn't have a high-level equivalent of `goto fail`... well Djikstra would probably say you shouldn't use that language in the first place, but given that you are, it's no worse than using `jlt .forloop` in assembly.
Re:Anti-If: The missing patterns (2016) by s-shellfish on Wednesday June 27, 2018 @06:23PM (#17412385)
You are going to wind up with some kind of 'goto' regardless, whether it's having to navigate through independent files or various other constructs one takes for granted as being immutable. The point being, when you notice them, automate them out of the reasoning space so you don't drown in the complexity of one mundane detail being used to represent the overall state of the program (all the stuff you have to shove in your head to understand what your program is doing).

These things are hard to notice, and even harder to find elegant and effective solutions!

The point is to reduce the problem space so all you are left to look at, when you do come back to your code, is what's important to reason about without removing important details or adding trivialities. These problems haven't gone away just because the literal word goto isn't used anymore.

Re:Anti-If: The missing patterns (2016) by sago on Wednesday June 27, 2018 @03:54PM (#17411269)
> If your language doesn't have a high-level equivalent of `goto fail`

Such as?

I am aware of writing this in different ways, of architecting the logic quite differently. But the only control-flow construct I've seen as alternatives are to abuse exceptions or labelled while with named breaks.

What were you thinking of when you wrote this? I'm genuinely interested.

Re:Anti-If: The missing patterns (2016) by reificator on Wednesday June 27, 2018 @04:09PM (#17411377)
Golang's defer statement gives some of that power, (and some extra guarantees) but doesn't as far as I know allow return statements.

You can however give named return values and reference those names, and I believe it will work.

I've not seen any other constructs in any language that would come close, and I still maintain `goto fail` is a reasonable construct.

Re:Anti-If: The missing patterns (2016) by mjevans on Wednesday June 27, 2018 @05:53PM (#17412153)
Deferred statements (in go) are really useful for delaying the runtime of blocks of code to the end of a context, but leaving them in the logical context where you're setting up a resource.

I'm actually not sure offhand how multiple deferred statements are handled. I could envision that the specification might make no explicit guarantee about the runtime order or it might create and pop off of a stack (at least in behavior).

Re:Anti-If: The missing patterns (2016) by sago on Wednesday June 27, 2018 @06:08PM (#17412283)
Thank you. For clarity, here would be the GP example:

   Foo foo = acquireFoo()
   defer releaseFoo(foo)

   if !isValid(foo) {
      return FAIL
   }

   moreWork(foo)
   return SUCCESS
That is impressively clear. I don't use go, myself.

I agree, I am quite comfortable using goto in C/C++ in this context. Though it may be better in C++ to use RAII in this specific example.

Re:Anti-If: The missing patterns (2016) by msla on Wednesday June 27, 2018 @06:48PM (#17412555)
Common Lisp has `with-open-file`, which guarantees files get closed regardless of what happens in the body, even if an exception is thrown (the macro closes the file and then propagates the exception in that case):

    (with-open-file (fhandle path)
        (if (has-record fhandle)
            (process-record (get-record fhandle))))
Python basically has this, but Python doesn't give you the macros needed to write your own for other kinds of resource.

http://clhs.lisp.se/Body/m_w_open.htm

> If a new output file is being written, and control leaves abnormally, the file is aborted and the file system is left, so far as possible, as if the file had never been opened.

Shades of PCLSRing!

Re:Anti-If: The missing patterns (2016) by sago on Wednesday June 27, 2018 @06:59PM (#17412622)
> Python doesn't give you the macros needed to write your own for other kinds of resource.

Python doesn't use macros, true. But it absolutely gives you the ability to do 'with' for other kinds of resource (and anything else). Look for the with-statement and documentation on defining your own context manager.

Re:Anti-If: The missing patterns (2016) by lokedhs on Wednesday June 27, 2018 @09:36PM (#17413409)
with-open-file is just a convenience macro around the underlying functionality which is provided by unwind-protect which is pretty much identical to try/finally in Java.

The ease of writing macros such as with-open-file means that most libraries that need to have similar types of features for their resources that needs releasing also provides similar functionality.

Re:Anti-If: The missing patterns (2016) by lawtguy on Wednesday June 27, 2018 @05:23PM (#17411973)
Java and C# have the `finally` block which is essentially the `goto fail`. Typically it is used like:

  try {
    doSomething();
  }
  catch (Exception e) {
    handleException();
  }
  finally {
    cleanUpResources();
  }
When the code exits the try block, you are guaranteed that it will run the finally block, possibly entering the catch block first if an exception was thrown. Since the most common use of `goto fail` pattern is freeing memory, the `finally` block isn't actually used a lot in Java/C# code in practice.
Re:Anti-If: The missing patterns (2016) by sago on Wednesday June 27, 2018 @06:05PM (#17412261)
Thank you. Since the example was nothing to do with exceptions, and we don't want to abuse exceptions by using them when they are not needed, I will rewrite your example to cover the GP case:

   Foo foo = acquireFoo();
   try {
       if (!isValid(foo)) {
          return FAIL;
       }
       moreWork(foo);
       return SUCCESS;
   } finally {
       releaseFoo(foo);
   }
Python could also use the same approach. Though it also has context managers / the with-statement for this specific application.
Re:Anti-If: The missing patterns (2016) by a1369209993 on Wednesday June 27, 2018 @09:31PM (#17413386)
> What were you thinking of when you wrote this? I'm genuinely interested.

That there is no high-level equivalent, and Djikstra, while he sometimes had useful insights, was ultimately a self-righteous twit.

Sorry to disappoint; I would also be interested a (not-even-worse-than-goto-like-exceptions-are) answer to your question.

Re:Anti-If: The missing patterns (2016) by reificator on Wednesday June 27, 2018 @04:01PM (#17411324)
I could be misunderstanding here, but I'm fairly sure that in the spirit of the paper `goto fail` would be preferable to throwing an exception and unwinding the stack at any arbitrary function call.
Re:Anti-If: The missing patterns (2016) by beagle3 on Wednesday June 27, 2018 @02:50PM (#17410744)
Dijkstra's original title was a "a case against the goto statement". The clickbait title "goto considered harmful" was chosen by the editor of the CACM

[0] https://www.cs.utexas.edu/users/EWD/transcriptions/EWD02xx/E...

Re:Anti-If: The missing patterns (2016) by octorian on Wednesday June 27, 2018 @12:06PM (#17409297)
I've extensively written code like this, though I don't seem to see others do it very often. I suppose if you really hate gotos, then a "do { } while(0);" with a "break;" in the middle of it is equivalent.

There's just too much cleanup, such that avoiding gotos means you're either nested 200 columns into the screen or have half your function filled with partially-duplicated cleanup code.

Re:Anti-If: The missing patterns (2016) by megous on Wednesday June 27, 2018 @02:54PM (#17410766)
gcc has __attribute__((cleanup)) extension for this:

https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attribute...

Re:Anti-If: The missing patterns (2016) by artpepper2 on Wednesday June 27, 2018 @03:50PM (#17411238)
I used this pattern a lot writing Win32 / COM code.