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.
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.
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.
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).
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.
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. 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. (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!
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.
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.
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.