www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - 'goto', as an indicator of good language

reply AnimusPEXUS <animuspexus protonmail.com> writes:
There was a discussion sometime ago in a Russian Dlang Telegram 
chat about 'goto' keyword. And there was some empiric theory, 
stating 'all good languages support goto statement'. Nor Rust, 
nor Carbon, nor Zig will never going to overcome D or C++ because 
of this. Language should give possibilities, not take them away. 
And in some cases, goto able to make code more readable, more 
sane and more understandable. Also, goto is much safer in 
language with GC.

[corresponding section in 
wikipedia](https://en.wikipedia.org/wiki/Goto#Criticism)
Sep 08 2022
next sibling parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 9/8/22 12:33 PM, AnimusPEXUS wrote:
 There was a discussion sometime ago in a Russian Dlang Telegram chat 
 about 'goto' keyword. And there was some empiric theory, stating 'all 
 good languages support goto statement'. Nor Rust, nor Carbon, nor Zig 
 will never going to overcome D or C++ because of this. Language should 
 give possibilities, not take them away. And in some cases, goto able to 
 make code more readable, more sane and more understandable. Also, goto 
 is much safer in language with GC.
 
 [corresponding section in 
 wikipedia](https://en.wikipedia.org/wiki/Goto#Criticism)
 
goto in D is sane. You cannot skip initializations. You cannot skip variable declarations. You can't jump into other functions. You can't jump out of or into certain things (e.g. a finally clause). Loops and if/switch statements are glorified gotos. If you need something different, goto can make code much much easier to read/write/understand rather than trying to shoehorn it into one of these other constructs. -Steve
Sep 08 2022
parent reply Walter Bright <newshound2 digitalmars.com> writes:
To be fair, nested functions along with function inlining has eliminated many
of 
the reasons that I use gotos.

Another reason for gotos is for ways of exiting loops without having to set 
flags that later control the flow.
Sep 08 2022
next sibling parent reply JN <666total wp.pl> writes:
On Thursday, 8 September 2022 at 22:47:33 UTC, Walter Bright 
wrote:
 To be fair, nested functions along with function inlining has 
 eliminated many of the reasons that I use gotos.

 Another reason for gotos is for ways of exiting loops without 
 having to set flags that later control the flow.
I find it surprising that no language added something like "break all;" instruction to exit all loops.
Sep 09 2022
parent jmh530 <john.michael.hall gmail.com> writes:
On Friday, 9 September 2022 at 09:30:21 UTC, JN wrote:
 On Thursday, 8 September 2022 at 22:47:33 UTC, Walter Bright 
 wrote:
 To be fair, nested functions along with function inlining has 
 eliminated many of the reasons that I use gotos.

 Another reason for gotos is for ways of exiting loops without 
 having to set flags that later control the flow.
I find it surprising that no language added something like "break all;" instruction to exit all loops.
D can break on labels, which is even more powerful than that. To be honest, I don't recall ever using it in my own code, but it works. ```d import core.stdc.stdio: printf; void main() { outer: for (size_t i = 0; i < 4; i++) { for (size_t j = 0; j < 4; j++) { if (i * j > 4) { break outer; } printf("i = %lu, j = %lu\n", i, j); } printf("i = %lu\n", i); } } ```
Sep 09 2022
prev sibling parent reply Nick Treleaven <nick geany.org> writes:
On Thursday, 8 September 2022 at 22:47:33 UTC, Walter Bright 
wrote:
 To be fair, nested functions along with function inlining has 
 eliminated many of the reasons that I use gotos.

 Another reason for gotos is for ways of exiting loops without 
 having to set flags that later control the flow.
Yeah, there's this code from dmd/dsymbolsem.d: ```d if (FuncDeclaration func = sc.parent.isFuncDeclaration()) { tm.symtab = func.localsymtab; if (tm.symtab) { // Inside template constraint, symtab is not set yet. goto L1; } } else { tm.symtab = sc.parent.isScopeDsymbol().symtab; L1: assert(tm.symtab); tm.ident = Identifier.generateId(s, tm.symtab.length + 1); tm.symtab.insert(tm); } ``` You can write it as: ```d (){ if (FuncDeclaration func = sc.parent.isFuncDeclaration()) { tm.symtab = func.localsymtab; if (!tm.symtab) return; // Inside template constraint, symtab is not set yet. } else tm.symtab = sc.parent.isScopeDsymbol().symtab; //L1: assert(tm.symtab); tm.ident = Identifier.generateId(s, tm.symtab.length + 1); tm.symtab.insert(tm); }(); ``` I'd prefer to write it as: ```d switch { if (FuncDeclaration func = sc.parent.isFuncDeclaration()) { tm.symtab = func.localsymtab; if (!tm.symtab) break; // Inside template constraint, symtab is not set yet. } else tm.symtab = sc.parent.isScopeDsymbol().symtab; //L1: assert(tm.symtab); tm.ident = Identifier.generateId(s, tm.symtab.length + 1); tm.symtab.insert(tm); } ``` Where `switch` works like `switch(0) default:` today. Using the function literal call means you can't return from the containing function, which may be needed.
Sep 09 2022
next sibling parent reply Paul Backus <snarwin gmail.com> writes:
On Friday, 9 September 2022 at 14:03:57 UTC, Nick Treleaven wrote:
 I'd prefer to write it as:
 ```d
     switch
     {
         if (FuncDeclaration func = 
 sc.parent.isFuncDeclaration())
         {
             tm.symtab = func.localsymtab;
             if (!tm.symtab) break;
             // Inside template constraint, symtab is not set 
 yet.
         }
         else
             tm.symtab = sc.parent.isScopeDsymbol().symtab;
     //L1:
         assert(tm.symtab);
         tm.ident = Identifier.generateId(s, tm.symtab.length + 
 1);
         tm.symtab.insert(tm);
     }
 ```
 Where `switch` works like `switch(0) default:` today.
I think maybe a more intuitive keyword for this would be `do`: ```d do { // ... if (whatever) break; // ... } ``` ...which would work like `do { ... } while (0);` currently does.
Sep 09 2022
parent Nick Treleaven <nick geany.org> writes:
On Friday, 9 September 2022 at 14:18:04 UTC, Paul Backus wrote:
 On Friday, 9 September 2022 at 14:03:57 UTC, Nick Treleaven 
 wrote:
 Where `switch` works like `switch(0) default:` today.
I think maybe a more intuitive keyword for this would be `do`: ```d do { // ... if (whatever) break; // ... } ``` ...which would work like `do { ... } while (0);` currently does.
So continue would do the same as break? Bit weird. Also you don't know if it's a loop or not until you find the closing brace. It's better to know in advance.
Sep 09 2022
prev sibling parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 9/9/22 10:03 AM, Nick Treleaven wrote:
 I'd prefer to write it as:
 ```d
      switch
      {
          if (FuncDeclaration func = sc.parent.isFuncDeclaration())
          {
              tm.symtab = func.localsymtab;
              if (!tm.symtab) break;
              // Inside template constraint, symtab is not set yet.
          }
          else
              tm.symtab = sc.parent.isScopeDsymbol().symtab;
      //L1:
          assert(tm.symtab);
          tm.ident = Identifier.generateId(s, tm.symtab.length + 1);
          tm.symtab.insert(tm);
      }
 ```
 Where `switch` works like `switch(0) default:` today.
 
 Using the function literal call means you can't return from the 
 containing function, which may be needed.
 
Instead of switch, you can use: ```d do { ... } while(false); ``` And then use a break inside. But honestly, all this looks like "I want to avoid goto at all costs". The original looks better to me. Another possibility that uses goto, but might be preferred, is: ```d if (FuncDeclaration func = sc.parent.isFuncDeclaration()) { tm.symtab = func.localsymtab; if (!tm.symtab) { // Inside template constraint, symtab is not set yet. goto L1; } } else { tm.symtab = sc.parent.isScopeDsymbol().symtab; } assert(tm.symtab); tm.ident = Identifier.generateId(s, tm.symtab.length + 1); tm.symtab.insert(tm); L1: ``` -Steve
Sep 09 2022
parent reply Nick Treleaven <nick geany.org> writes:
On Friday, 9 September 2022 at 14:22:51 UTC, Steven Schveighoffer 
wrote:
 Instead of switch, you can use:
 ```d
 do {
    ...
 } while(false);
 ```

 And then use a break inside.
Not the same, continue applies to the do then, not an outer loop. Also not clear until the end of the construct that it's not a loop.
 But honestly, all this looks like "I want to avoid goto at all 
 costs". The original looks better to me.
It's easier to reason about switch because you don't have to read the whole function looking for the matching label.
 Another possibility that uses goto, but might be preferred, is:

 ```d
     if (FuncDeclaration func = sc.parent.isFuncDeclaration())
     {
         tm.symtab = func.localsymtab;
         if (!tm.symtab)
         {
             // Inside template constraint, symtab is not set 
 yet.
             goto L1;
         }
     }
     else
     {
         tm.symtab = sc.parent.isScopeDsymbol().symtab;
     }
     assert(tm.symtab);
     tm.ident = Identifier.generateId(s, tm.symtab.length + 1);
     tm.symtab.insert(tm);
 L1:
 ```
That's an improvement.
Sep 09 2022
parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 9/9/22 11:40 AM, Nick Treleaven wrote:
 On Friday, 9 September 2022 at 14:22:51 UTC, Steven Schveighoffer wrote:
 Instead of switch, you can use:
 ```d
 do {
    ...
 } while(false);
 ```

 And then use a break inside.
Not the same, continue applies to the do then, not an outer loop. Also not clear until the end of the construct that it's not a loop.
If we are talking about wrapping existing code that might contain a continue, you need to also consider that the existing code might contain a break. In both cases, you could label the target and use a targeted continue or break statement. But again, goto is better here.
 
 But honestly, all this looks like "I want to avoid goto at all costs". 
 The original looks better to me.
It's easier to reason about switch because you don't have to read the whole function looking for the matching label.
You don't though. Just search for it. Just like you would have to search for the matching closing brace of the switch. At least in the case of the label, you can use text search, and not have to account for nested braces. -Steve
Sep 09 2022
parent reply Nick Treleaven <nick geany.org> writes:
On Friday, 9 September 2022 at 15:57:45 UTC, Steven Schveighoffer 
wrote:
 On 9/9/22 11:40 AM, Nick Treleaven wrote:
 On Friday, 9 September 2022 at 14:22:51 UTC, Steven 
 Schveighoffer wrote:
 Instead of switch, you can use:
 ```d
 do {
    ...
 } while(false);
 ```

 And then use a break inside.
Not the same, continue applies to the do then, not an outer loop. Also not clear until the end of the construct that it's not a loop.
If we are talking about wrapping existing code that might contain a continue, you need to also consider that the existing code might contain a break. In both cases, you could label the target and use a targeted continue or break statement.
If you know there's no break but there is a continue, you don't have to use a label.
 But again, goto is better here.

 
 But honestly, all this looks like "I want to avoid goto at 
 all costs". The original looks better to me.
It's easier to reason about switch because you don't have to read the whole function looking for the matching label.
You don't though. Just search for it. Just like you would have to search for the matching closing brace of the switch. At least in the case of the label, you can use text search, and not have to account for nested braces.
Why would you need to stop reading the code sequentially and lookup the closing brace? With goto you need to to understand what you're looking at. That's my point.
Sep 09 2022
parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 9/9/22 12:31 PM, Nick Treleaven wrote:
 On Friday, 9 September 2022 at 15:57:45 UTC, Steven Schveighoffer wrote:
 On 9/9/22 11:40 AM, Nick Treleaven wrote:
 Not the same, continue applies to the do then, not an outer loop. 
 Also not clear until the end of the construct that it's not a loop.
If we are talking about wrapping existing code that might contain a continue, you need to also consider that the existing code might contain a break. In both cases, you could label the target and use a targeted continue or break statement.
If you know there's no break but there is a continue, you don't have to use a label.
So when you say "Not the same", you mean that <1% difference.
 It's easier to reason about switch because you don't have to read the 
 whole function looking for the matching label.
You don't though. Just search for it. Just like you would have to search for the matching closing brace of the switch. At least in the case of the label, you can use text search, and not have to account for nested braces.
Why would you need to stop reading the code sequentially and lookup the closing brace? With goto you need to to understand what you're looking at. That's my point.
If the closing brace is close at hand, then the appropriate label would be too. It will even stand out more. But you are saying "read the whole function". I'm assuming you mean that it's far away from the break/goto statement. If it's off-screen, the label wins hands-down. Using my editor I can find "L1:" much easier than I can find a specific "}" -Steve
Sep 09 2022
parent Nick Treleaven <nick geany.org> writes:
On Friday, 9 September 2022 at 17:04:44 UTC, Steven Schveighoffer 
wrote:
 So when you say "Not the same", you mean that <1% difference.
That's where bugs hide.
 It's easier to reason about switch because you don't have to 
 read the whole function looking for the matching label.
You don't though. Just search for it. Just like you would have to search for the matching closing brace of the switch. At least in the case of the label, you can use text search, and not have to account for nested braces.
Why would you need to stop reading the code sequentially and lookup the closing brace? With goto you need to to understand what you're looking at. That's my point.
If the closing brace is close at hand, then the appropriate label would be too. It will even stand out more. But you are saying "read the whole function". I'm assuming you mean that it's far away from the break/goto statement. If it's off-screen, the label wins hands-down. Using my editor I can find "L1:" much easier than I can find a specific "}"
Why do I need to stop reading the code sequentially and find the closing brace of a switch? I do not. Searching for a label *is disruptive*, even if automated, it breaks my train of thought. With goto the matching label could be inside the switch or it could be outside it, at different levels of scope. With break, you know it just jumps to the end of the switch. When I'm reading code, I'm trying to understand each statement. I can't understand a goto without knowing which scope it goes to. With break you know what scope that is. This is a key part of why we have structured programming, because you know where the code will go to when exiting a construct.
Sep 10 2022
prev sibling next sibling parent reply IGotD- <nise nise.com> writes:
On Thursday, 8 September 2022 at 16:33:58 UTC, AnimusPEXUS wrote:
 There was a discussion sometime ago in a Russian Dlang Telegram 
 chat about 'goto' keyword. And there was some empiric theory, 
 stating 'all good languages support goto statement'. Nor Rust, 
 nor Carbon, nor Zig will never going to overcome D or C++ 
 because of this. Language should give possibilities, not take 
 them away. And in some cases, goto able to make code more 
 readable, more sane and more understandable. Also, goto is much 
 safer in language with GC.

 [corresponding section in 
 wikipedia](https://en.wikipedia.org/wiki/Goto#Criticism)
Does this apply to all languages or only "systems languages"? If we look at current popular heavy lifting languages. Support goto: Objective-C Do not support goto: Python Java Swift It seems to be a bit too simplistic criteria to me. Anyway, I haven't used goto a lot in C/C++ other than in "roll back error handling". D manage to do this even better with with its scope guards. How does other languages handle "roll back error handling" (is there a better terminology for this?).
Sep 08 2022
next sibling parent AnimusPEXUS <animuspexus protonmail.com> writes:
On Thursday, 8 September 2022 at 17:04:28 UTC, IGotD- wrote:
 Does this apply to all languages or only "systems languages"?
I think it's apply to any General-purpose language
 If we look at current popular heavy lifting languages.
 Support goto:

 Objective-C
Go supports too
Sep 08 2022
prev sibling parent Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Thursday, 8 September 2022 at 17:04:28 UTC, IGotD- wrote:
 Anyway, I haven't used goto a lot in C/C++ other than in "roll 
 back error handling". D manage to do this even better with with 
 its scope guards. How does other languages handle "roll back 
 error handling" (is there a better terminology for this?).
Exceptions? Goto is useful when implementing state machines, the resulting code is often more readable.
Sep 09 2022
prev sibling next sibling parent reply Dukc <ajieskola gmail.com> writes:
On Thursday, 8 September 2022 at 16:33:58 UTC, AnimusPEXUS wrote:
 There was a discussion sometime ago in a Russian Dlang Telegram 
 chat about 'goto' keyword. And there was some empiric theory, 
 stating 'all good languages support goto statement'. Nor Rust, 
 nor Carbon, nor Zig will never going to overcome D or C++ 
 because of this. Language should give possibilities, not take 
 them away. And in some cases, goto able to make code more 
 readable, more sane and more understandable. Also, goto is much 
 safer in language with GC.

 [corresponding section in 
 wikipedia](https://en.wikipedia.org/wiki/Goto#Criticism)
My personal attitude to `goto` is that it's overhated. While it's true that conditional and loop statements are mostly better, an occasional `goto` is not necessarily a code smell. Also I'd be much more worried about mutable `static`/global variables and oversized functions/types than a few needless `goto`s in a module. I suspect it's bad reputation is from the times when some (non-assembly) languages did not have structured programming and everything was done with `goto`s. Going back to that sure would suck, but there's quite a difference between an occasional `goto` and replacing all your loops with it. sometimes prefer it, but when I resort to it in D I usually notice a better way shortly afterwards. I'd be slightly annoyed to live without it but could easily cope.
Sep 08 2022
next sibling parent reply "H. S. Teoh" <hsteoh qfbox.info> writes:
On Thu, Sep 08, 2022 at 08:39:30PM +0000, Dukc via Digitalmars-d wrote:
 On Thursday, 8 September 2022 at 16:33:58 UTC, AnimusPEXUS wrote:
 There was a discussion sometime ago in a Russian Dlang Telegram chat
 about 'goto' keyword. And there was some empiric theory, stating
 'all good languages support goto statement'. Nor Rust, nor Carbon,
 nor Zig will never going to overcome D or C++ because of this.
 Language should give possibilities, not take them away. And in some
 cases, goto able to make code more readable, more sane and more
 understandable. Also, goto is much safer in language with GC.
 
 [corresponding section in
 wikipedia](https://en.wikipedia.org/wiki/Goto#Criticism)
My personal attitude to `goto` is that it's overhated. While it's true that conditional and loop statements are mostly better, an occasional `goto` is not necessarily a code smell. Also I'd be much more worried about mutable `static`/global variables and oversized functions/types than a few needless `goto`s in a module. I suspect it's bad reputation is from the times when some (non-assembly) languages did not have structured programming and everything was done with `goto`s. Going back to that sure would suck, but there's quite a difference between an occasional `goto` and replacing all your loops with it.
[...] Also keep in mind that `goto` in modern-day languages is a very different thing from `goto` in the old days. In the old days, it was the equivalent of a `jmp` instruction in assembly language; it could literally jump *anywhere* in the program, including jump from the middle of function A into the middle of function B where B isn't even on the call stack. It would skip variable cleanups and initializations, stack adjustments, etc., and generally produce *really* unreadable code. (See, for example, GOTO in old versions of BASIC, that lets you jump to any arbitrary line in your program.) It's even more powerful (and dangerous) than C's longjmp(), because the destination of the goto doesn't even have to be on the call stack or anywhere near where the history of execution has passed. The `goto` of today's languages is a much safer, de-fanged version of the original goto. In D, for example, you cannot `goto` out of a function (or into another). The compiler also doesn't let you skip variable initializations / destructions. So it's subject to pretty much the same constraints as "structured" constructs like if, while, for, switch, etc., except it's more low-level and can do a few more things that the other constructs can't do. So yes, you can overuse `goto` in your function and make it hard to follow, but then nested if-else blocks and loops that span 5000 lines are also hard to read[1], so it's not saying very much. And today's goto is nowhere near as wild as the original `goto` in the old days. [1] I'm not making this up, I've actually seen 5000+ line functions in real-world "enterprise" code. They are one of those things you wish you never have to debug, because you just can't fully understand what they do, goto or not. T -- Always remember that you are unique. Just like everybody else. -- despair.com
Sep 08 2022
parent reply Dukc <ajieskola gmail.com> writes:
On Thursday, 8 September 2022 at 21:03:04 UTC, H. S. Teoh wrote:
 The `goto` of today's languages is a much safer, de-fanged 
 version of the original goto. In D, for example, you cannot 
 `goto` out of a function (or into another). The compiler also 
 doesn't let you skip variable initializations / destructions. 
 So it's subject to pretty much the same constraints as 
 "structured" constructs like if, while, for, switch, etc., 
 except it's more low-level and can do a few more things that 
 the other constructs can't do.
Well if I really wanted to I could do it in 60s style by putting everything inside a giant `switch(callStack.pop)` in `main()`. "functions" would be just `goto` labels, called like this: ```D callStack.push(something); goto function; case something: ``` ...with a jump to the switch at end of each "function" body. So `goto` does technically have as long fangs as always :D. Of course, modern languages do a good job encouraging better coding habits.
Sep 08 2022
parent "H. S. Teoh" <hsteoh qfbox.info> writes:
On Thu, Sep 08, 2022 at 09:30:06PM +0000, Dukc via Digitalmars-d wrote:
 On Thursday, 8 September 2022 at 21:03:04 UTC, H. S. Teoh wrote:
 The `goto` of today's languages is a much safer, de-fanged version
 of the original goto. In D, for example, you cannot `goto` out of a
 function (or into another). The compiler also doesn't let you skip
 variable initializations / destructions. So it's subject to pretty
 much the same constraints as "structured" constructs like if, while,
 for, switch, etc., except it's more low-level and can do a few more
 things that the other constructs can't do.
Well if I really wanted to I could do it in 60s style by putting everything inside a giant `switch(callStack.pop)` in `main()`. "functions" would be just `goto` labels, called like this: ```D callStack.push(something); goto function; case something: ``` ...with a jump to the switch at end of each "function" body.
Still can't get around variable initializations / destructions. ;-) Plus, if your code ever interacts with mine, it would not be able to willy-nilly goto into my function, no matter what other atrocities it's committing inside main(). In 60s style code, you'd just `lea` to get the address of the target function, perform pointer arithmetic, and `jmp` to the destination, whether or not the callee wants to be called that way or not. :-D Fortunately, such nonsense is blocked at the language level.
 So `goto` does technically have as long fangs as always :D. Of course,
 modern languages do a good job encouraging better coding habits.
Well, that's kinda an unfair way to look at it. I mean, if I *really* wanted to write code like the above, I don't even need `goto`; it suffices to just write something like this: void main() { int state = 1; int globalVar; switch (state) { case 1: doSomething(); globalVar++; state = 5; break; case 2: doSomethingElse(); globalVar--; state = 3; break; case 3: doYetSomethingElse(); globalVar += 2; state = 6; break; case 4: blahblahblah(); globalVar -= 2; state = 1; break; case 5: andSoOn(); globalVar *= 2; state = 2; break; case 6: justForKicks(); globalVar /= 3; state = uniform(1, 7); break; } } I mean, I could write an assembly language emulator in main(), and write the worst possible random-jump-ridden, self-mutating virus code that main() would execute, but that doesn't mean D is inherently bad because it's possible to do so. T -- "Real programmers can write assembly code in any language. :-)" -- Larry Wall
Sep 08 2022
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
goto can be handy to avoid needing to refactor a bunch of code when fixing a 
problem.

The refactoring can come later in its own PR.
Sep 08 2022
parent reply max haughton <maxhaton gmail.com> writes:
On Thursday, 8 September 2022 at 22:49:05 UTC, Walter Bright 
wrote:
 goto can be handy to avoid needing to refactor a bunch of code 
 when fixing a problem.

 The refactoring can come later in its own PR.
It almost never does though, let's be realistic.
Sep 08 2022
next sibling parent "H. S. Teoh" <hsteoh qfbox.info> writes:
On Fri, Sep 09, 2022 at 12:26:44AM +0000, max haughton via Digitalmars-d wrote:
 On Thursday, 8 September 2022 at 22:49:05 UTC, Walter Bright wrote:
 goto can be handy to avoid needing to refactor a bunch of code
 when fixing a problem.
 
 The refactoring can come later in its own PR.
It almost never does though, let's be realistic.
IME, typically code stinks come about this way: 1) Original code is reasonably clean and well-written. 2) A critical bug is discovered 2 days before the release deadline. 3) In the mad rush to get the release out the door, Good-Hearted possible. He comforts himself, "I will clean up this messy hack code after the release." makes it out the door on time. There is celebration, and o' days to recover from the release. code, PTB walks in and hands him High Priority Project X that has to be done by last week. He gets totally occupied with Project X and forgets about cleaning up the code. 6) Meanwhile, another release deadline looms, and another bug is himself, "There's no time to figure this out, I'll just patch over the code and redo the fix properly after the release." to a different company altogether. And so layer upon layer of hacks and bandages are accumulated on top of the code, the well-intentioned cleanups never happen. Soon, so much cruft has accumulated that nobody knows how to clean it up anymore. Instead, the bugs and quirky behaviours are worked around and patched over, and customers begin relying on the quirky behaviour, further cementing it forever. T -- MACINTOSH: Most Applications Crash, If Not, The Operating System Hangs
Sep 08 2022
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 9/8/2022 5:26 PM, max haughton wrote:
 The refactoring can come later in its own PR.
It almost never does though, let's be realistic.
Quite a few of my PRs are refactorings.
Sep 08 2022
parent reply max haughton <maxhaton gmail.com> writes:
On Friday, 9 September 2022 at 02:00:28 UTC, Walter Bright wrote:
 On 9/8/2022 5:26 PM, max haughton wrote:
 The refactoring can come later in its own PR.
It almost never does though, let's be realistic.
Quite a few of my PRs are refactorings.
You are much better than most in this regard but my point is that every at some point thinks "This is the million dollar goto, I've been waiting for this moment all year" or just that one goto couldn't posssibbblyy hurt, and locally they might well be right but in my experience with the exception of tight interpreter loops I *very* rarely see truly justified uses for goto. They might look clever but they're usually a symptom of code that is to abstraction/design what goto is to structured control flow. If the code does eventually get refactored then great but especially in a professional environment where you might be more able to manage a larger refactoring, it's better to pay the refactoring cost now rather than later if at all possible. Another more subtle psychological factor against using goto is that sometimes gotos are actually worth it, fair enough, but now other people working on the code can see the goto in the corner of their eye and think they can program like it's 1999 and blame it on the goto. Replacing gotos with a void function call return is a nice pattern that D luckily makes trivial to use, for anyone reading unaware of the pattern.
Sep 09 2022
parent JG <someone simewhere.com> writes:
On Saturday, 10 September 2022 at 06:27:32 UTC, max haughton 
wrote:
 Replacing gotos with a void function call return is a nice 
 pattern that D luckily makes trivial to use, for anyone reading 
 unaware of the pattern.
Just to be sure could you please give a small example.
Sep 10 2022
prev sibling parent user1234 <user1234 12.de> writes:
On Thursday, 8 September 2022 at 16:33:58 UTC, AnimusPEXUS wrote:
 There was a discussion sometime ago in a Russian Dlang Telegram 
 chat about 'goto' keyword. And there was some empiric theory, 
 stating 'all good languages support goto statement'. Nor Rust, 
 nor Carbon, nor Zig will never going to overcome D or C++
 because of this. Language should give possibilities, not take 
 them away.
This is what Zig did see https://github.com/ziglang/zig/issues/630. I think that the rationale is quite good. Goto solves *almost* no problem.
 And in some cases, goto able to make code more readable, more 
 sane and more understandable. Also, goto is much safer in 
 language with GC.
That's a good point.
 [corresponding section in 
 wikipedia](https://en.wikipedia.org/wiki/Goto#Criticism)
See also https://wiki.c2.com/?GoodUseOfGoto
Sep 09 2022