www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - goto a no-go?

reply "Chris" <wendlec tcd.ie> writes:
Just a short question. Usually goto statements are frowned upon 
as being bad programming style (in textbooks at least). D has it 
(thankfully) and I've used it, albeit sparingly. Sometimes goto 
is simply the best and most efficient solution within a code 
block (to avoid code duplication, unnecessary checks or 
redirecting to yet another function blah blah). Is it ok or even 
necessary to use goto in D? Or does the compiler recognize 
_obvious_ cases and generate code accordingly? For example would 
it turn something like this

// ...
if (word.length == 1) {
  // format output
  return output;
} else if (word.length > 1) {
   // do some additional processing
   // format output
   return output;
}

into

// ...
if (word.length == 1) goto FormatOutput;

// if word.length > 1, some extra work has to be done
// initialize some variables, parse, do some processing etc.

FormatOutput:
  // .....

return output;
Oct 01 2013
next sibling parent reply "Dicebot" <public dicebot.lv> writes:
 // ...
 if (word.length == 1) goto FormatOutput;

 // if word.length > 1, some extra work has to be done
 // initialize some variables, parse, do some processing etc.

 FormatOutput:
  // .....

 return output;
Have never felt need to use `goto` since got familiar with `scope(something)` : http://dpaste.dzfl.pl/ca40b3b6 ;)
Oct 01 2013
next sibling parent reply "Chris" <wendlec tcd.ie> writes:
On Tuesday, 1 October 2013 at 11:26:54 UTC, Dicebot wrote:
 // ...
 if (word.length == 1) goto FormatOutput;

 // if word.length > 1, some extra work has to be done
 // initialize some variables, parse, do some processing etc.

 FormatOutput:
 // .....

 return output;
Have never felt need to use `goto` since got familiar with `scope(something)` : http://dpaste.dzfl.pl/ca40b3b6 ;)
Thanks, this is what I was looking for, a more elegant solution. I was going through some old code and saw the odd goto statement. scope() shows of course that some sort of goto mechanism is pretty handy (no matter what the textbooks say).
Oct 01 2013
parent reply "Dicebot" <public dicebot.lv> writes:
On Tuesday, 1 October 2013 at 11:35:35 UTC, Chris wrote:
 Thanks, this is what I was looking for, a more elegant 
 solution. I was going through some old code and saw the odd 
 goto statement. scope() shows of course that some sort of goto 
 mechanism is pretty handy (no matter what the textbooks say).
goto is not avoided because of functionality it enables but because of unhygienic way it is implemented. scope guards offer part of that functionality in much more clean and safe way and there is nothing wrong about using them.
Oct 01 2013
parent "Chris" <wendlec tcd.ie> writes:
On Tuesday, 1 October 2013 at 12:13:18 UTC, Dicebot wrote:
 On Tuesday, 1 October 2013 at 11:35:35 UTC, Chris wrote:
 Thanks, this is what I was looking for, a more elegant 
 solution. I was going through some old code and saw the odd 
 goto statement. scope() shows of course that some sort of goto 
 mechanism is pretty handy (no matter what the textbooks say).
goto is not avoided because of functionality it enables but because of unhygienic way it is implemented. scope guards offer part of that functionality in much more clean and safe way and there is nothing wrong about using them.
That was my point.
Oct 01 2013
prev sibling parent reply "Jesse Phillips" <Jesse.K.Phillips+D gmail.com> writes:
On Tuesday, 1 October 2013 at 11:26:54 UTC, Dicebot wrote:
 // ...
 if (word.length == 1) goto FormatOutput;

 // if word.length > 1, some extra work has to be done
 // initialize some variables, parse, do some processing etc.

 FormatOutput:
 // .....

 return output;
Have never felt need to use `goto` since got familiar with `scope(something)` : http://dpaste.dzfl.pl/ca40b3b6 ;)
if (word.length) scope(exit) FormatOutput(); This is the same as if (word.length) FormatOutput(); The `if` introduces a new scope, thus running the code right away.
Oct 02 2013
parent reply "Dicebot" <public dicebot.lv> writes:
On Wednesday, 2 October 2013 at 16:12:58 UTC, Jesse Phillips 
wrote:
     if (word.length)
         scope(exit) FormatOutput();

 This is the same as

     if (word.length)
         FormatOutput();

 The `if` introduces a new scope, thus running the code right 
 away.
Oops, shame on me. Too many `static if`s in my life :(
Oct 02 2013
next sibling parent "monarch_dodra" <monarchdodra gmail.com> writes:
On Wednesday, 2 October 2013 at 17:06:40 UTC, Dicebot wrote:
 On Wednesday, 2 October 2013 at 16:12:58 UTC, Jesse Phillips 
 wrote:
    if (word.length)
        scope(exit) FormatOutput();

 This is the same as

    if (word.length)
        FormatOutput();

 The `if` introduces a new scope, thus running the code right 
 away.
Oops, shame on me. Too many `static if`s in my life :(
I think it might be a common mistake? I remember making a similar error by placing a scope(exit) in a for loop, hoping they'd all get run when leaving the function.
Oct 02 2013
prev sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 10/2/13 10:06 AM, Dicebot wrote:
 On Wednesday, 2 October 2013 at 16:12:58 UTC, Jesse Phillips wrote:
     if (word.length)
         scope(exit) FormatOutput();

 This is the same as

     if (word.length)
         FormatOutput();

 The `if` introduces a new scope, thus running the code right away.
Oops, shame on me. Too many `static if`s in my life :(
I think it's a common mishap. Might be nice if the compiler disallowed gramatically an unbraced if/while/etc containing only one scope statement. Andrei
Oct 02 2013
parent reply "deadalnix" <deadalnix gmail.com> writes:
On Thursday, 3 October 2013 at 02:21:19 UTC, Andrei Alexandrescu 
wrote:
 On 10/2/13 10:06 AM, Dicebot wrote:
 On Wednesday, 2 October 2013 at 16:12:58 UTC, Jesse Phillips 
 wrote:
    if (word.length)
        scope(exit) FormatOutput();

 This is the same as

    if (word.length)
        FormatOutput();

 The `if` introduces a new scope, thus running the code right 
 away.
Oops, shame on me. Too many `static if`s in my life :(
I think it's a common mishap. Might be nice if the compiler disallowed gramatically an unbraced if/while/etc containing only one scope statement. Andrei
Or more generally cope statement at the end of a scope.
Oct 02 2013
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 10/2/13 8:14 PM, deadalnix wrote:
 On Thursday, 3 October 2013 at 02:21:19 UTC, Andrei Alexandrescu wrote:
 On 10/2/13 10:06 AM, Dicebot wrote:
 On Wednesday, 2 October 2013 at 16:12:58 UTC, Jesse Phillips wrote:
    if (word.length)
        scope(exit) FormatOutput();

 This is the same as

    if (word.length)
        FormatOutput();

 The `if` introduces a new scope, thus running the code right away.
Oops, shame on me. Too many `static if`s in my life :(
I think it's a common mishap. Might be nice if the compiler disallowed gramatically an unbraced if/while/etc containing only one scope statement. Andrei
Or more generally cope statement at the end of a scope.
I'm cautious about that; that's why I specified "unbraced". Consider: if (lily) { scope(exit) writeln("Lily was here."); // fun(); } This code is a plausible edit of work that was meaningful and in which the programmer has temporarily commented out the call to fun. If the compiler would obnoxiously protest that the edited code can't compile, that may be more aggravation than win for the user. In contrast, this is no simple edit of any sensible code: if (lily) scope(exit) writeln("Lily was here."); Here, the compiler is much more within its rights to demand a code change, either to scope(exit) if (lily) writeln("Lily was here."); or if (lily) writeln("Lily was here."); or if (lily) { scope(exit) writeln("Lily was here."); } Andrei
Oct 02 2013
next sibling parent "deadalnix" <deadalnix gmail.com> writes:
On Thursday, 3 October 2013 at 03:37:27 UTC, Andrei Alexandrescu 
wrote:
 I'm cautious about that; that's why I specified "unbraced". 
 Consider:

 if (lily)
 {
     scope(exit) writeln("Lily was here.");
     // fun();
 }

 This code is a plausible edit of work that was meaningful and 
 in which the programmer has temporarily commented out the call 
 to fun. If the compiler would obnoxiously protest that the 
 edited code can't compile, that may be more aggravation than 
 win for the user.
It is also fairly common to add control flow that make code unrechable in dev (or when playing with static ifs). And it is disallowed.
Oct 02 2013
prev sibling parent Dmitry Olshansky <dmitry.olsh gmail.com> writes:
03-Oct-2013 07:37, Andrei Alexandrescu пишет:
 On 10/2/13 8:14 PM, deadalnix wrote:
 On Thursday, 3 October 2013 at 02:21:19 UTC, Andrei Alexandrescu wrote:
 On 10/2/13 10:06 AM, Dicebot wrote:
[snip]
 Or more generally cope statement at the end of a scope.
I'm cautious about that; that's why I specified "unbraced". Consider: if (lily) { scope(exit) writeln("Lily was here."); // fun(); } This code is a plausible edit of work that was meaningful and in which the programmer has temporarily commented out the call to fun. If the compiler would obnoxiously protest that the edited code can't compile, that may be more aggravation than win for the user. In contrast, this is no simple edit of any sensible code: if (lily) scope(exit) writeln("Lily was here."); Here, the compiler is much more within its rights to demand a code change, either to scope(exit) if (lily) writeln("Lily was here."); or if (lily) writeln("Lily was here.");
Truth be told I'd be _very_ cautious of the tiny special cases like this, they make generating D code (including at CTFE) a PITA. -- Dmitry Olshansky
Oct 11 2013
prev sibling next sibling parent "qznc" <qznc web.de> writes:
On Tuesday, 1 October 2013 at 11:22:12 UTC, Chris wrote:
 Just a short question. Usually goto statements are frowned upon 
 as being bad programming style (in textbooks at least). D has 
 it (thankfully) and I've used it, albeit sparingly. Sometimes 
 goto is simply the best and most efficient solution within a 
 code block (to avoid code duplication, unnecessary checks or 
 redirecting to yet another function blah blah). Is it ok or 
 even necessary to use goto in D? Or does the compiler recognize 
 _obvious_ cases and generate code accordingly? For example 
 would it turn something like this

 // ...
 if (word.length == 1) {
  // format output
  return output;
 } else if (word.length > 1) {
   // do some additional processing
   // format output
   return output;
 }

 into

 // ...
 if (word.length == 1) goto FormatOutput;

 // if word.length > 1, some extra work has to be done
 // initialize some variables, parse, do some processing etc.

 FormatOutput:
  // .....

 return output;
How is that transformation an optimization or improvement? Substituting "return output" for "goto FormatOutput" is not better. So, I assume "// format output" is the code duplication you want to remove? Well, your example should also work like this: if (word.length > 1) { // do some additional processing } // format output return output; Regarding goto and D, scope guards [0] are good for removing gotos, because the cleanup-after-error code can be moved. [0] http://dlang.org/statement.html#ScopeGuardStatement
Oct 01 2013
prev sibling next sibling parent reply Manu <turkeyman gmail.com> writes:
On 1 October 2013 21:22, Chris <wendlec tcd.ie> wrote:

 Just a short question. Usually goto statements are frowned upon as being
 bad programming style (in textbooks at least). D has it (thankfully) and
 I've used it, albeit sparingly. Sometimes goto is simply the best and most
 efficient solution within a code block (to avoid code duplication,
 unnecessary checks or redirecting to yet another function blah blah). Is it
 ok or even necessary to use goto in D? Or does the compiler recognize
 _obvious_ cases and generate code accordingly? For example would it turn
 something like this

 // ...
 if (word.length == 1) {
  // format output
  return output;
 } else if (word.length > 1) {
   // do some additional processing
   // format output
   return output;
 }

 into

 // ...
 if (word.length == 1) goto FormatOutput;

 // if word.length > 1, some extra work has to be done
 // initialize some variables, parse, do some processing etc.

 FormatOutput:
  // .....

 return output;
Well, obviously that should be rewritten: if (word.length > 1) { // additional processing } // format output return output; Note: there's an un-handled case in your example, but I'll ignore that. Anyway, goto is supported. Walter likes it. I use it from time to time. I'd say 90% of the time I find goto useful is when I need to bail from nested loops. I've often wondered if something like break(2) would be a more elegant solution to the breaking out of nested loops problem. But in direct answer to your question, I think you'll find modern optimisers are smart enough to make the optimisation you are looking for. I haven't tested that precise case, but I've definitely expected the optimiser to do the right thing in similar cases, and it does. I rarely write code that requires me to have faith in any optimiser though.
Oct 01 2013
next sibling parent reply "John Colvin" <john.loughran.colvin gmail.com> writes:
On Tuesday, 1 October 2013 at 11:40:35 UTC, Manu wrote:
 I'd say 90% of the time I find goto useful is when I need to 
 bail from
 nested loops. I've often wondered if something like break(2) 
 would be a
 more elegant solution to the breaking out of nested loops 
 problem.
labeled statements to the rescue! outer: foreach(i; 0..10) { foreach(j; 0..10) { break outer; } }
Oct 01 2013
parent reply "monarch_dodra" <monarchdodra gmail.com> writes:
On Tuesday, 1 October 2013 at 11:47:37 UTC, John Colvin wrote:
 On Tuesday, 1 October 2013 at 11:40:35 UTC, Manu wrote:
 I'd say 90% of the time I find goto useful is when I need to 
 bail from
 nested loops. I've often wondered if something like break(2) 
 would be a
 more elegant solution to the breaking out of nested loops 
 problem.
labeled statements to the rescue! outer: foreach(i; 0..10) { foreach(j; 0..10) { break outer; } }
break outer; Obsoletes one of my "only" use cases where before, I would have used a goto instead: foreach(i; 0..10) { foreach(j; 0..10) { goto double_break; } } double_break: {} It's awesome. Too bad you can't break from an arbitrary block though. It can help avoiding the dreaded "if(if(if(if(...))))" pattern, as well as the "bool didYouDoIt" pattern. I still have to use my "goto after_block" pattern :/ //---- //Search and deal with a specific condition //While doing something special if the condition is not found. { if (some_condition) goto block_end; //No need to do anything if (some_other_condition) goto block_end; //No need to do anything if (some_third_condition) goto block_end; //No need to do anything for (...) { for (...) { if (...) { do_processing(); goto block_end; //We found what we wanted. } } } do_code_for_not_found_here(); } done_processing: {} //Keep going here //---- I guess I can always use the "do{}while(false);" pattern, but I actually find it *more* confusing (IMO)
Oct 01 2013
next sibling parent reply "Dicebot" <public dicebot.lv> writes:
Can't you use scope guards for that too? Those work for any 
scope, not only function scope.
Oct 01 2013
parent reply "monarch_dodra" <monarchdodra gmail.com> writes:
On Tuesday, 1 October 2013 at 12:46:50 UTC, Dicebot wrote:
 Can't you use scope guards for that too? Those work for any 
 scope, not only function scope.
I hadn't thought of that before, but I don't think so. scope guards are designed to run a specific piece of code, no mater the code path. What I mostly want to do is just break out of a "control block". Either that, or I'm being retarded...?
Oct 01 2013
parent reply "Dicebot" <public dicebot.lv> writes:
On Tuesday, 1 October 2013 at 13:02:56 UTC, monarch_dodra wrote:
 On Tuesday, 1 October 2013 at 12:46:50 UTC, Dicebot wrote:
 Can't you use scope guards for that too? Those work for any 
 scope, not only function scope.
I hadn't thought of that before, but I don't think so. scope guards are designed to run a specific piece of code, no mater the code path. What I mostly want to do is just break out of a "control block". Either that, or I'm being retarded...?
In that case you can always replace "control block + goto" with nested function + return + scope guard inside it (if some cleanup code needs to be run) unless I am missing something. (I think your snippet misses actual labels so it was unclear:))
Oct 01 2013
parent "monarch_dodra" <monarchdodra gmail.com> writes:
On Tuesday, 1 October 2013 at 13:09:01 UTC, Dicebot wrote:
 On Tuesday, 1 October 2013 at 13:02:56 UTC, monarch_dodra wrote:
 On Tuesday, 1 October 2013 at 12:46:50 UTC, Dicebot wrote:
 Can't you use scope guards for that too? Those work for any 
 scope, not only function scope.
I hadn't thought of that before, but I don't think so. scope guards are designed to run a specific piece of code, no mater the code path. What I mostly want to do is just break out of a "control block". Either that, or I'm being retarded...?
(I think your snippet misses actual labels so it was unclear:))
Right, sorry.
 In that case you can always replace "control block + goto" with 
 nested function + return + scope guard inside it (if some 
 cleanup code needs to be run) unless I am missing something.
I was going to say: "but using functions is a pain when you have variables that are in scope you need to reuse", but I keep forgetting that D can indeed nest functions. The only "limitation" of using a nested function, as opposed to a "breakable block", is that can't move code into a nested function, if it contains a (conditional) return. I guess the conclusion is that each code snippet is unique. With enough effort, you can probably eliminate goto from almost any example. I do find that sometimes, you tend to have to jump through hoops for that tough, and the final code is not necessarily "better" either.
Oct 01 2013
prev sibling parent Nick Treleaven <ntrel-public yahoo.co.uk> writes:
On 01/10/2013 13:36, monarch_dodra wrote:
 I guess I can always use the "do{}while(false);" pattern, but I actually
 find it *more* confusing (IMO)
Although it might not get used that often, it might be nice if D allowed omitting the 'while(false)' part, just using a semi-colon for 'do' termination: do { ... if (cond) break; // exit do ... // implicit fall through, no looping unless 'continue' is used };
Oct 02 2013
prev sibling next sibling parent "Chris" <wendlec tcd.ie> writes:
On Tuesday, 1 October 2013 at 11:40:35 UTC, Manu wrote:
 On 1 October 2013 21:22, Chris <wendlec tcd.ie> wrote:

 Just a short question. Usually goto statements are frowned 
 upon as being
 bad programming style (in textbooks at least). D has it 
 (thankfully) and
 I've used it, albeit sparingly. Sometimes goto is simply the 
 best and most
 efficient solution within a code block (to avoid code 
 duplication,
 unnecessary checks or redirecting to yet another function blah 
 blah). Is it
 ok or even necessary to use goto in D? Or does the compiler 
 recognize
 _obvious_ cases and generate code accordingly? For example 
 would it turn
 something like this

 // ...
 if (word.length == 1) {
  // format output
  return output;
 } else if (word.length > 1) {
   // do some additional processing
   // format output
   return output;
 }

 into

 // ...
 if (word.length == 1) goto FormatOutput;

 // if word.length > 1, some extra work has to be done
 // initialize some variables, parse, do some processing etc.

 FormatOutput:
  // .....

 return output;
Well, obviously that should be rewritten: if (word.length > 1) { // additional processing } // format output return output;
 Note: there's an un-handled case in your example, but I'll 
 ignore that.
That was just a made up example (of an obvious case). The real case was a bit more complicated (involving an associative array).
 Anyway, goto is supported. Walter likes it. I use it from time 
 to time.
 I'd say 90% of the time I find goto useful is when I need to 
 bail from
 nested loops. I've often wondered if something like break(2) 
 would be a
 more elegant solution to the breaking out of nested loops 
 problem.

 But in direct answer to your question, I think you'll find 
 modern
 optimisers are smart enough to make the optimisation you are 
 looking for. I
 haven't tested that precise case, but I've definitely expected 
 the
 optimiser to do the right thing in similar cases, and it does. 
 I rarely
 write code that requires me to have faith in any optimiser 
 though.
Sure, but it's good to know that some sub-optimal code is optimized, until I find the time to optimize it by hand. Optimizing too early can be more harmful than sub-optimal code (that is just a wee bit slower but harmless).
Oct 01 2013
prev sibling parent reply "deadalnix" <deadalnix gmail.com> writes:
On Tuesday, 1 October 2013 at 11:40:35 UTC, Manu wrote:
 Note: there's an un-handled case in your example, but I'll 
 ignore that.
 Anyway, goto is supported. Walter likes it. I use it from time 
 to time.
 I'd say 90% of the time I find goto useful is when I need to 
 bail from
 nested loops. I've often wondered if something like break(2) 
 would be a
 more elegant solution to the breaking out of nested loops 
 problem.
BreakableLoop: while(condition) { while(condition) { // Stuff . . . break BreakableLoop; } } Also works with continue.
Oct 01 2013
parent reply Manu <turkeyman gmail.com> writes:
On 1 October 2013 23:54, deadalnix <deadalnix gmail.com> wrote:

 On Tuesday, 1 October 2013 at 11:40:35 UTC, Manu wrote:

 Note: there's an un-handled case in your example, but I'll ignore that.
 Anyway, goto is supported. Walter likes it. I use it from time to time.
 I'd say 90% of the time I find goto useful is when I need to bail from
 nested loops. I've often wondered if something like break(2) would be a
 more elegant solution to the breaking out of nested loops problem.
BreakableLoop: while(condition) { while(condition) { // Stuff . . . break BreakableLoop; } } Also works with continue.
... O_O Is this D code? I've never seen that. If that works, that's awesome!
Oct 01 2013
next sibling parent "monarch_dodra" <monarchdodra gmail.com> writes:
On Tuesday, 1 October 2013 at 16:55:12 UTC, Manu wrote:
 On 1 October 2013 23:54, deadalnix <deadalnix gmail.com> wrote:

 On Tuesday, 1 October 2013 at 11:40:35 UTC, Manu wrote:

 Note: there's an un-handled case in your example, but I'll 
 ignore that.
 Anyway, goto is supported. Walter likes it. I use it from 
 time to time.
 I'd say 90% of the time I find goto useful is when I need to 
 bail from
 nested loops. I've often wondered if something like break(2) 
 would be a
 more elegant solution to the breaking out of nested loops 
 problem.
BreakableLoop: while(condition) { while(condition) { // Stuff . . . break BreakableLoop; } } Also works with continue.
... O_O Is this D code?
Yup :)
 I've never seen that. If that works, that's awesome!
Yup :)
Oct 01 2013
prev sibling next sibling parent reply "deadalnix" <deadalnix gmail.com> writes:
On Tuesday, 1 October 2013 at 16:55:12 UTC, Manu wrote:
 On 1 October 2013 23:54, deadalnix <deadalnix gmail.com> wrote:

 On Tuesday, 1 October 2013 at 11:40:35 UTC, Manu wrote:

 Note: there's an un-handled case in your example, but I'll 
 ignore that.
 Anyway, goto is supported. Walter likes it. I use it from 
 time to time.
 I'd say 90% of the time I find goto useful is when I need to 
 bail from
 nested loops. I've often wondered if something like break(2) 
 would be a
 more elegant solution to the breaking out of nested loops 
 problem.
BreakableLoop: while(condition) { while(condition) { // Stuff . . . break BreakableLoop; } } Also works with continue.
... O_O Is this D code? I've never seen that. If that works, that's awesome!
Yes, I use it quite a lot ! Very useful construct.
Oct 01 2013
parent Manu <turkeyman gmail.com> writes:
On 2 October 2013 03:00, deadalnix <deadalnix gmail.com> wrote:

 On Tuesday, 1 October 2013 at 16:55:12 UTC, Manu wrote:

 On 1 October 2013 23:54, deadalnix <deadalnix gmail.com> wrote:

  On Tuesday, 1 October 2013 at 11:40:35 UTC, Manu wrote:
  Note: there's an un-handled case in your example, but I'll ignore that.
 Anyway, goto is supported. Walter likes it. I use it from time to time.
 I'd say 90% of the time I find goto useful is when I need to bail from
 nested loops. I've often wondered if something like break(2) would be a
 more elegant solution to the breaking out of nested loops problem.


  BreakableLoop: while(condition) {
while(condition) { // Stuff . . . break BreakableLoop; } } Also works with continue.
... O_O Is this D code? I've never seen that. If that works, that's awesome!
Yes, I use it quite a lot ! Very useful construct.
Super useful! :) Well, I think there's almost no reason left for goto... I can't think of any of my common use cases that aren't satisfied with a proper D construct.
Oct 01 2013
prev sibling parent "Dicebot" <public dicebot.lv> writes:
On Tuesday, 1 October 2013 at 16:55:12 UTC, Manu wrote:
 Is this D code?
 I've never seen that. If that works, that's awesome!
http://dlang.org/statement.html#BreakStatement "If break is followed by Identifier, the Identifier must be the label of an enclosing while, for, do or switch statement, and that statement is exited. It is an error if there is no such statement."
Oct 01 2013
prev sibling next sibling parent "Jakob Ovrum" <jakobovrum gmail.com> writes:
On Tuesday, 1 October 2013 at 11:22:12 UTC, Chris wrote:
 Is it ok or even necessary to use goto in D?
It's best viewed as a compatibility or micro-optimization feature. For structuring code, D obsoletes goto with nested functions, scope statements and labelled break and continue. Most experienced D programmers use scope statements and labelled break/continue to replace goto with great effect, but sometimes the same programmers can still be seen using goto when a nested function would really have solved the issue more structurally, so I recommend experimenting with nested functions if they are unfamiliar to you.
Oct 01 2013
prev sibling next sibling parent Jos van Uden <usenet fwend.com> writes:
On 1-10-2013 13:22, Chris wrote:

Is it ok or even necessary to use goto in D?
I doubt it's necessary but it can be useful sometimes. In the Markov algorithm at Rosetta code I used it to restart a loop, including reinitializing a variable. I'm sure it could have been done without goto but it was convenient. http://rosettacode.org/wiki/Markov_Algorithm#D
Oct 01 2013
prev sibling next sibling parent "Gary Willoughby" <dev nomad.so> writes:
On Tuesday, 1 October 2013 at 11:22:12 UTC, Chris wrote:
 Sometimes goto is simply the best and most efficient solution 
 within a code block (to avoid code duplication, unnecessary 
 checks or redirecting to yet another function blah blah).
News to me! I haven't used goto in 15 years of development as there are always more elegant ways of designing software. The only reason i can see goto being properly used is in machine generated code where no developer will be maintaining it.
Oct 01 2013
prev sibling next sibling parent Unknown <kozzi11 gmail.com> writes:
Manu píše v Út 01. 10. 2013 v 21:40 +1000:


 I'd say 90% of the time I find goto useful is when I need to bail from
 nested loops. I've often wondered if something like break(2) would be
 a more elegant solution to the breaking out of nested loops problem.
I use break SomeLabel for this situations: FirstLoop: while(1) { SecondLoop: while(1) { break FirstLoop; } }
Oct 01 2013
prev sibling next sibling parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
Nobody mentioned the use of goto with switch-case.

   http://ddili.org/ders/d.en/switch_case.html

goto can appear in three ways under case sections:

* 'goto case' causes the execution to continue to the next case.

* 'goto default' causes the execution to continue to the default section.

* 'goto expression' causes the execution to continue to the case that 
matches that expression.

The following program demonstrates these three uses by taking advantage 
of a foreach loop:

import std.stdio;

void main()
{
     foreach (value; [ 1, 2, 3, 10, 20 ]) {
         writefln("--- value: %s ---", value);

         switch (value) {

         case 1:
             writeln("case 1");
             goto case;

         case 2:
             writeln("case 2");
             goto case 10;

         case 3:
             writeln("case 3");
             goto default;

         case 10:
             writeln("case 10");
             break;

         default:
             writeln("default");
             break;
         }
     }
}

The output:

--- value: 1 ---
case 1
case 2
case 10
--- value: 2 ---
case 2
case 10
--- value: 3 ---
case 3
default
--- value: 10 ---
case 10
--- value: 20 ---
default

Ali
Oct 01 2013
next sibling parent reply "monarch_dodra" <monarchdodra gmail.com> writes:
On Tuesday, 1 October 2013 at 17:15:34 UTC, Ali Çehreli wrote:
 Nobody mentioned the use of goto with switch-case.

   http://ddili.org/ders/d.en/switch_case.html

 goto can appear in three ways under case sections:

 * 'goto case' causes the execution to continue to the next case.
 [SNIP]
 Ali
Hum... What is the difference between "goto case" and "continue" in a switch statement?
Oct 01 2013
parent "monarch_dodra" <monarchdodra gmail.com> writes:
On Tuesday, 1 October 2013 at 19:45:20 UTC, monarch_dodra wrote:
 On Tuesday, 1 October 2013 at 17:15:34 UTC, Ali Çehreli wrote:
 Nobody mentioned the use of goto with switch-case.

  http://ddili.org/ders/d.en/switch_case.html

 goto can appear in three ways under case sections:

 * 'goto case' causes the execution to continue to the next 
 case.
 [SNIP]
 Ali
Hum... What is the difference between "goto case" and "continue" in a switch statement?
Never-mind, I seem to have been confused. I thought "continue" was the keyword to use for explicit fall-through. Carry on then.
Oct 01 2013
prev sibling parent reply "Jakob Ovrum" <jakobovrum gmail.com> writes:
On Tuesday, 1 October 2013 at 17:15:34 UTC, Ali Çehreli wrote:
 Nobody mentioned the use of goto with switch-case.
Those are goto-case statements, not goto statements. I don't think it's a useful notion to associate the two beyond the fact that they share a keyword in their syntax.
Oct 01 2013
parent reply "monarch_dodra" <monarchdodra gmail.com> writes:
On Wednesday, 2 October 2013 at 06:19:24 UTC, Jakob Ovrum wrote:
 On Tuesday, 1 October 2013 at 17:15:34 UTC, Ali Çehreli wrote:
 Nobody mentioned the use of goto with switch-case.
Those are goto-case statements, not goto statements. I don't think it's a useful notion to associate the two beyond the fact that they share a keyword in their syntax.
Well, it remains a "go to this piece of code" command. Now, you can write a program as a single giant switch that jumps around from state to state, without it ever ending. Like in one of those "read your own adventure books" int page = 1; switch(1) { case 1: writeln("you arrive in a large chamber... To light a torch, go to page 196) To run through, go to page 155"; readfln("%s", &page); goto page; etc... } That's a pretty sweet construct actually :)
Oct 02 2013
parent "Gary Willoughby" <dev nomad.so> writes:
On Wednesday, 2 October 2013 at 08:15:04 UTC, monarch_dodra wrote:
 That's a pretty sweet construct actually :)
No it isn't, that is awful code.
Oct 02 2013
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 10/1/2013 4:22 AM, Chris wrote:
 Or does the compiler recognize _obvious_ cases and generate code
 accordingly? For example would it turn something like this
Actually, the dmd compiler turns ALL control flow into goto statements internally, then the optimizer works on that. For example, it reverse engineers loops from a graph of basic blocks connected by goto's.
Oct 01 2013
parent "deadalnix" <deadalnix gmail.com> writes:
On Tuesday, 1 October 2013 at 18:47:27 UTC, Walter Bright wrote:
 On 10/1/2013 4:22 AM, Chris wrote:
 Or does the compiler recognize _obvious_ cases and generate 
 code
 accordingly? For example would it turn something like this
Actually, the dmd compiler turns ALL control flow into goto statements internally, then the optimizer works on that. For example, it reverse engineers loops from a graph of basic blocks connected by goto's.
Most compiler do that.
Oct 01 2013