5 ms·
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 d
by agateau 8y ago
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.
- reificator 8y ago> 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.
- monocasa 8y agoYeah. 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.
- bitL 8y agoKeep 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.
- monocasa 8y agoNot 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.
- bitL 8y agoWell, 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.
- astrobe_ 8y agoIt 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.
- monocasa 8y agoThere'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.
- astrobe_ 8y agoWell, 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.
- a1369209993 8y agoDjikstra'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.
- sago 8y ago> 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.
- reificator 8y agoGolang'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.
- mjevans 8y agoDeferred 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).
- deleted 8y ago[deleted]
- 8y ago
- beagle3 8y agoDijkstra'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/EWD215.html https://www.cs.utexas.edu/users/EWD/transcriptions/EWD02xx/E...
- octorian 8y agoI'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.
- megous 8y agogcc has __attribute__((cleanup)) extension for this: https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html#Common-Variable-Attributes https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attribute...
- artpepper2 8y agoI used this pattern a lot writing Win32 / COM code.