4 ms·
I feel like "goto" gets an unfair bad reputation. It really can be useful at times.
by RandomInteger4 10y ago
I feel like "goto" gets an unfair bad reputation. It really can be useful at times.
- ap22213 10y agoUntil the time at which another developer must debug it and all previously gained value instantly disappears (at least in imperative languages)
- carterehsmith 10y agoI think you are talking about something else, not goto. Did you mean 'exceptions'?
- Tideflat 10y agoIn vanilla C, exceptions do not exist. Thus goto is the standard (at least for the Linux kernel) statement for handling exceptions.
- carterehsmith 10y agoOh, I see. Is that something like setjmp/longjmp?
- unwind 10y agoNo, it's just plain goto, to a named label which is (for this case) later in the function. It's quite common in low-level code where you want to do a bunch of things that can all fail, and you need to rewind and undo the things that succeeded up to the point of failure. See http://stackoverflow.com/questions/13001067/why-do-some-kernel-programmers-use-goto-instead-of-simple-while-loops http://stackoverflow.com/questions/13001067/why-do-some-kern... and https://www.kernel.org/doc/Documentation/CodingStyle https://www.kernel.org/doc/Documentation/CodingStyle (chapter 7 but that's raw text so I can't link).
- marrs 10y agoI wrote a simple set of c/++ macros to encapsulate this functionality, though it still relies on the dev to unwind in the correct order #define HANDLE_ERROR(label) bool label = false; #define ENSURE(label, pred) if (!(pred)) { label = true; goto label; } #define RESOLVE(label) label: if (label) HANDLE_ERROR statements go at the beginning of the block, RESOLVEs go at the end, in the reverse order to the ENSUREs, which go wherever they're required. It's been working well for me so far.
- marrs 10y agoLet me try that again with formatting this time: #define HANDLE_ERROR(label) bool label = false; #define ENSURE(label, pred) if (!(pred)) { label = true; goto label; } #define RESOLVE(label) label: if (label)
- carterehsmith 10y agoOK, then. The OP mentioned "previously gained value instantly disappears". I do not see what exactly disappears with GOTO?
- m_mueller 10y agoplease explain how a forward goto is more difficult to debug than a loop, branch or switch. I'm not advocating to replace those with gotos btw., except for early jumps to cleanup phases.
- Rangi42 10y agoIf you can rely on the developer to use gotos in clear patterns like that, then great. But if there is a recognizable pattern, it's an opportunity for the language to provide an alternative like with{} or try{}finally{}.
- m_mueller 10y agoI agree with with{}, less so with try/finally. First of all, I think exceptions are at least as easy to get wrong in your application (or worse system) design as goto. And if you get them wrong, it's probably even harder to debug. Second of all, the resulting code is IMO far less readable. To illustrate - which would you prefer: a = None try: a = get_ressource_a() b = None try: b = get_ressource_b(a) process(a,b) except BException as e: handle_errors(e) finally: cleanup_b(b) except AException as e: handle_errors(e) finally: cleanup_a(a) or a = get_ressource_a() if not a: handle_errors() return b = get_ressource_b(a) if not b: handle_errors() goto cleanup_a process(a,b) cleanup_b: #do the cleanup cleanup_a: #do the cleanup My dream language would have more or less Python's syntax, with dynamic, inferred, but strong types, no exception handling, and instead Swift's "optional" baked into the language and a very smart logging that I can peak into with the error handler. The error handler could be the only sideeffect allowed when a function is declared pure. I don't need goto if with{} works well with such a system.
- klibertp 10y agoWhat about Nim[1]? It provides nearly everything you mention and covers the "finally" case with `defer`. Worth looking at - I re-implemented suckless' slock in Nim[2][3] and it was very pleasant experience. [1] http://nim-lang.org/ [2] https://klibert.pl/posts/slock_in_nim.html [3] https://github.com/piotrklibert/nimlock
- OskarS 10y agoA good use for it is to exit early from deeply nested loops, which normally would require several "break"s. Some languages (Java, for instance) support "named breaks", but they tend to be more confusing than just using a goto. This is more or less the only time I would use a goto over similar constructions like switch/case or continue/break.