Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. Other Discussions
  3. The Weird and The Wonderful
  4. Avoid return statement in the middle - horror or not?

Avoid return statement in the middle - horror or not?

Scheduled Pinned Locked Moved The Weird and The Wonderful
question
59 Posts 28 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • R Robert C Cartaino

    harold aptroot wrote:

    Java also seems to behave differently from what you said:

    I think you are right. I was looking at this section[^] of the Java language specification: 15.7.2 Evaluate Operands before Operation The Java programming language also guarantees that every operand of an operator (except the conditional operators &&, ||, and ? : ) appears to be fully evaluated before any part of the operation itself is performed. They do explicitly exempt the logical operators. Let's hope that && is not overloaded -- in C++ at least -- then short circuiting does not apply. Then I was reading this on C++ Sequence Points[^]. It says that "the left operand of the logical AND operator is completely evaluated and all side effects completed before continuing. There is no guarantee that the right operand of the logical AND operator will be evaluated. Of course, it doesn't say that is guaranteed not to be evaluated, either. Then it says this: "The controlling expression in a selection (if or switch) statement. The expression is completely evaluated and all side effects completed before the code dependent on the selection is executed." So, who knows. My conclusion would be that a C/C++ compiler is indeed supposed to do left-right evaluation and short circuiting. But I still say it's irrelevant. If I have to hunt that hard to get down into the bowels of how a compiler works to determine how my code will execute, I say it's a bad programming practice. I'll take these guys word for it: ...The moral is that writing code that depends on order of evaluation is a bad programming practice in any language. Naturally, it is necessary to know what things to avoid, but if you don't know how they are done on various machines, you won't be tempted to take advantage of a particular implementation. -- The C Programming Language[

    L Offline
    L Offline
    Lost User
    wrote on last edited by
    #14

    Ah good ol' C and C++ with their lack of guarantees :) Now that is a real horror :laugh:

    1 Reply Last reply
    0
    • R Robert C Cartaino

      harold aptroot wrote:

      Java also seems to behave differently from what you said:

      I think you are right. I was looking at this section[^] of the Java language specification: 15.7.2 Evaluate Operands before Operation The Java programming language also guarantees that every operand of an operator (except the conditional operators &&, ||, and ? : ) appears to be fully evaluated before any part of the operation itself is performed. They do explicitly exempt the logical operators. Let's hope that && is not overloaded -- in C++ at least -- then short circuiting does not apply. Then I was reading this on C++ Sequence Points[^]. It says that "the left operand of the logical AND operator is completely evaluated and all side effects completed before continuing. There is no guarantee that the right operand of the logical AND operator will be evaluated. Of course, it doesn't say that is guaranteed not to be evaluated, either. Then it says this: "The controlling expression in a selection (if or switch) statement. The expression is completely evaluated and all side effects completed before the code dependent on the selection is executed." So, who knows. My conclusion would be that a C/C++ compiler is indeed supposed to do left-right evaluation and short circuiting. But I still say it's irrelevant. If I have to hunt that hard to get down into the bowels of how a compiler works to determine how my code will execute, I say it's a bad programming practice. I'll take these guys word for it: ...The moral is that writing code that depends on order of evaluation is a bad programming practice in any language. Naturally, it is necessary to know what things to avoid, but if you don't know how they are done on various machines, you won't be tempted to take advantage of a particular implementation. -- The C Programming Language[

      P Offline
      P Offline
      PIEBALDconsult
      wrote on last edited by
      #15

      From the ANSI C99 spec I have: " 6.5.13-4 Unlike the bitwise & operator, the && operator guarantees left-to-right evaluation; there is a sequence point after the evaluation of the first operand. If the first operand compares equal to 0, the second operand is not evaluated. " Even Ritchie's C manual from 1974 says it's left-to-right. (It appears that B does not have these operators.) In the K&R book, they're talking about a[i]=i++, not the && operator, plus that's a very old book. You may certainly go right ahead and write code any way you like... I do.

      1 Reply Last reply
      0
      • R riced

        Having been brought up on 'Structured Programming' I used to think that one-entry and one-exit point was the only way to write procedures. Now I'm in favour of your approach - i.e. use guard conditions and exit early if need be. Oh and keep the procedure small, roughly no more than can fit on an A4 page. One example of how not to do it that I came across was a C++ function that had around 500 lines of code with about 15 returns scattered throughout. It also had a couple of places where it could throw an exception! David Rice

        P Offline
        P Offline
        PIEBALDconsult
        wrote on last edited by
        #16

        Having one return statement is still a worthwhile goal. You just have to look at it both ways and decide which is "better" in each individual case. I don't recall encountering any situations that required multiple return statements.

        1 Reply Last reply
        0
        • G Georgi Atanasov

          I have a coding rule - avoid "return" somewhere in the middle of a method, try using local variables to compensate instead. Observing this leads to the following (seen in existing code):

          if(flagA)
          {
          if(flagB)
          {
          if(flagC)
          {
          if(PromtUser())
          {
          DoSomething();
          }
          else
          {
          DoOtherThing();
          }
          }
          else
          {
          DoOtherThing();
          }
          }
          else
          {
          DoOtherThing();
          }
          }
          else
          {
          DoOtherThing();
          }

          How I would have written this is:

          if(flagA)
          {
          if(flagB)
          {
          if(flagC)
          {
          if(PromptUser())
          {
          return;
          }
          }
          }
          }

          DoOtherThing();

          I was wondering how you guys feel about it?

          Thanks, Georgi

          M Offline
          M Offline
          Michael Dunn
          wrote on last edited by
          #17

          You can't make a rule like that because there is no one correct rule that works for every single function you're going to write in your life. Well, you can make the rule, but doing so will be counter-productive. Why create a state machine with local variables in a function (and don't forget to test every possible state!), just to avoid using a perfectly valid language feature?

          --Mike-- Visual C++ MVP :cool: LINKS~! CP SearchBar v3.0 | C++ Forum FAQ I work for Keyser Söze

          U 1 Reply Last reply
          0
          • G Georgi Atanasov

            I have a coding rule - avoid "return" somewhere in the middle of a method, try using local variables to compensate instead. Observing this leads to the following (seen in existing code):

            if(flagA)
            {
            if(flagB)
            {
            if(flagC)
            {
            if(PromtUser())
            {
            DoSomething();
            }
            else
            {
            DoOtherThing();
            }
            }
            else
            {
            DoOtherThing();
            }
            }
            else
            {
            DoOtherThing();
            }
            }
            else
            {
            DoOtherThing();
            }

            How I would have written this is:

            if(flagA)
            {
            if(flagB)
            {
            if(flagC)
            {
            if(PromptUser())
            {
            return;
            }
            }
            }
            }

            DoOtherThing();

            I was wondering how you guys feel about it?

            Thanks, Georgi

            A Offline
            A Offline
            Andrew Torrance
            wrote on last edited by
            #18

            Single exit , single entry . Its a mantra that leads to clarity how about if( !FlagA || !FlagB || !FlagC) // Select Variant on !Flagx or Flagx == false depending on language DoOtherThing(); else { if(PromptUser()) DoSomething(); } Not a horror though. My use of single entry and exit points in functions leads to more debates than anything. (My how the winter nights fly by)

            R P 2 Replies Last reply
            0
            • A Andrew Torrance

              Single exit , single entry . Its a mantra that leads to clarity how about if( !FlagA || !FlagB || !FlagC) // Select Variant on !Flagx or Flagx == false depending on language DoOtherThing(); else { if(PromptUser()) DoSomething(); } Not a horror though. My use of single entry and exit points in functions leads to more debates than anything. (My how the winter nights fly by)

              R Offline
              R Offline
              Robert C Cartaino
              wrote on last edited by
              #19

              Andrew Torrance wrote:

              if( !FlagA || !FlagB || !FlagC) // Select Variant on !Flagx or Flagx == false depending on language DoOtherThing(); else { if(PromptUser()) DoSomething(); }

              ...except if PromptUser() fails, you also have to execute DoOtherThing(). So you need to add to your code:

              if( !FlagA || !FlagB || !FlagC) // Select Variant on !Flagx or Flagx == false depending on language
              DoOtherThing();
              else
              {
              if(PromptUser())
              DoSomething();
              else DoOtherThing();
              }

              1 Reply Last reply
              0
              • A Andrew Torrance

                Single exit , single entry . Its a mantra that leads to clarity how about if( !FlagA || !FlagB || !FlagC) // Select Variant on !Flagx or Flagx == false depending on language DoOtherThing(); else { if(PromptUser()) DoSomething(); } Not a horror though. My use of single entry and exit points in functions leads to more debates than anything. (My how the winter nights fly by)

                P Offline
                P Offline
                PIEBALDconsult
                wrote on last edited by
                #20

                How is that better than what I posted?

                B G 2 Replies Last reply
                0
                • R Robert C Cartaino

                  [Message Deleted]

                  M Offline
                  M Offline
                  Mladen Jankovic
                  wrote on last edited by
                  #21

                  Robert.C.Cartaino wrote:

                  Writing code that depends on order of evaluation is bad programming practice

                  If order of evaluation is not defined by the specification of the language, which is not true for logical operators in C/C++. According to your statement one should not write something like this:

                  if( node && node->value )
                  node->value->Do();

                  Instead you need to have another if for this simple operation even if the previous example is perfectly legal and clean and the desired behavior is guaranteed by the language specification. Well I guess that the only bad programming practice here is that someone introduces unneeded code because he doesn't trust/know language.

                  [Genetic Algorithm Library]

                  P 1 Reply Last reply
                  0
                  • M Mladen Jankovic

                    Robert.C.Cartaino wrote:

                    Writing code that depends on order of evaluation is bad programming practice

                    If order of evaluation is not defined by the specification of the language, which is not true for logical operators in C/C++. According to your statement one should not write something like this:

                    if( node && node->value )
                    node->value->Do();

                    Instead you need to have another if for this simple operation even if the previous example is perfectly legal and clean and the desired behavior is guaranteed by the language specification. Well I guess that the only bad programming practice here is that someone introduces unneeded code because he doesn't trust/know language.

                    [Genetic Algorithm Library]

                    P Offline
                    P Offline
                    PIEBALDconsult
                    wrote on last edited by
                    #22

                    Indeed. And should we question the order/precedence of the other operators as well? Can we trust 3 + 4 * 5 to return 23? or might it return 35 once in a while? I'm all for adding parentheses for clarity, but I don't get that confused with necessity.

                    1 Reply Last reply
                    0
                    • P PIEBALDconsult

                      How is that better than what I posted?

                      B Offline
                      B Offline
                      Ben Fair
                      wrote on last edited by
                      #23

                      Yes, he just inverted the boolean logic and made it worse in my opinion. if(!FlagA || !FlagB) is essentially the same as if(FlagA && FlagB) but I'd rather see the latter and that's how I'd do it in my code.

                      Keep It Simple Stupid! (KISS)

                      1 Reply Last reply
                      0
                      • P PIEBALDconsult

                        How is that better than what I posted?

                        G Offline
                        G Offline
                        geoffs
                        wrote on last edited by
                        #24

                        It's not. Your code was how I would have done it...

                        1 Reply Last reply
                        0
                        • M Michael Dunn

                          You can't make a rule like that because there is no one correct rule that works for every single function you're going to write in your life. Well, you can make the rule, but doing so will be counter-productive. Why create a state machine with local variables in a function (and don't forget to test every possible state!), just to avoid using a perfectly valid language feature?

                          --Mike-- Visual C++ MVP :cool: LINKS~! CP SearchBar v3.0 | C++ Forum FAQ I work for Keyser Söze

                          U Offline
                          U Offline
                          User 167261
                          wrote on last edited by
                          #25

                          it all depends on how much coffe i've had for the day...

                          do or do not, there is no try

                          P 1 Reply Last reply
                          0
                          • U User 167261

                            it all depends on how much coffe i've had for the day...

                            do or do not, there is no try

                            P Offline
                            P Offline
                            PIEBALDconsult
                            wrote on last edited by
                            #26

                            Drinking coffee leads to good code. Drinking "energy drinks" leads to poor code.

                            1 Reply Last reply
                            0
                            • G Georgi Atanasov

                              I have a coding rule - avoid "return" somewhere in the middle of a method, try using local variables to compensate instead. Observing this leads to the following (seen in existing code):

                              if(flagA)
                              {
                              if(flagB)
                              {
                              if(flagC)
                              {
                              if(PromtUser())
                              {
                              DoSomething();
                              }
                              else
                              {
                              DoOtherThing();
                              }
                              }
                              else
                              {
                              DoOtherThing();
                              }
                              }
                              else
                              {
                              DoOtherThing();
                              }
                              }
                              else
                              {
                              DoOtherThing();
                              }

                              How I would have written this is:

                              if(flagA)
                              {
                              if(flagB)
                              {
                              if(flagC)
                              {
                              if(PromptUser())
                              {
                              return;
                              }
                              }
                              }
                              }

                              DoOtherThing();

                              I was wondering how you guys feel about it?

                              Thanks, Georgi

                              F Offline
                              F Offline
                              FatBuddha
                              wrote on last edited by
                              #27

                              Assuming that there is more processing going on than this example indicates, I would use a do-while-false loop:

                              do{
                              if(!flagA)break;
                              if(!flagB)break;
                              if(!flagC)break;
                              if(!PromptUser())break;
                              }while(0);

                              DoOtherThing();

                              This is the sort of thing that I routinely do with COM programming where I need to check the success of pretty much every single method call. It means that I don't have a crazy amount of indenting, and it's much cleaner for me or somebody else to understand and modify later. I can highly recommend it.

                              None

                              P 1 Reply Last reply
                              0
                              • G Georgi Atanasov

                                I have a coding rule - avoid "return" somewhere in the middle of a method, try using local variables to compensate instead. Observing this leads to the following (seen in existing code):

                                if(flagA)
                                {
                                if(flagB)
                                {
                                if(flagC)
                                {
                                if(PromtUser())
                                {
                                DoSomething();
                                }
                                else
                                {
                                DoOtherThing();
                                }
                                }
                                else
                                {
                                DoOtherThing();
                                }
                                }
                                else
                                {
                                DoOtherThing();
                                }
                                }
                                else
                                {
                                DoOtherThing();
                                }

                                How I would have written this is:

                                if(flagA)
                                {
                                if(flagB)
                                {
                                if(flagC)
                                {
                                if(PromptUser())
                                {
                                return;
                                }
                                }
                                }
                                }

                                DoOtherThing();

                                I was wondering how you guys feel about it?

                                Thanks, Georgi

                                R Offline
                                R Offline
                                rfidel
                                wrote on last edited by
                                #28

                                Not sure if this made one of the previous replies, but what I found works best, and is easy to follow, is to iteratively step thru what I do not want, making use "else if" statements. After weeding thru all the crap, then what I am left with, is (usually) what I want. if(!flagA) { DoOtherThing(); } else if(!flagB) { DoOtherThing(); } else if(!flagC) { DoOtherThing(); } else if(!PromtUser()) { DoOtherThing(); } else { DoSomething(); }

                                P 1 Reply Last reply
                                0
                                • R rfidel

                                  Not sure if this made one of the previous replies, but what I found works best, and is easy to follow, is to iteratively step thru what I do not want, making use "else if" statements. After weeding thru all the crap, then what I am left with, is (usually) what I want. if(!flagA) { DoOtherThing(); } else if(!flagB) { DoOtherThing(); } else if(!flagC) { DoOtherThing(); } else if(!PromtUser()) { DoOtherThing(); } else { DoSomething(); }

                                  P Offline
                                  P Offline
                                  PIEBALDconsult
                                  wrote on last edited by
                                  #29

                                  That's simply the first snippet inverted and made even uglier. It's still a maintenance nightmare.

                                  1 Reply Last reply
                                  0
                                  • F FatBuddha

                                    Assuming that there is more processing going on than this example indicates, I would use a do-while-false loop:

                                    do{
                                    if(!flagA)break;
                                    if(!flagB)break;
                                    if(!flagC)break;
                                    if(!PromptUser())break;
                                    }while(0);

                                    DoOtherThing();

                                    This is the sort of thing that I routinely do with COM programming where I need to check the success of pretty much every single method call. It means that I don't have a crazy amount of indenting, and it's much cleaner for me or somebody else to understand and modify later. I can highly recommend it.

                                    None

                                    P Offline
                                    P Offline
                                    PIEBALDconsult
                                    wrote on last edited by
                                    #30

                                    Where's the call to DoSomething? I'm pretty sure that's not applicable to the original post.

                                    F 1 Reply Last reply
                                    0
                                    • P PIEBALDconsult

                                      Where's the call to DoSomething? I'm pretty sure that's not applicable to the original post.

                                      F Offline
                                      F Offline
                                      FatBuddha
                                      wrote on last edited by
                                      #31

                                      Doh - I was looking at the second code listing. Assuming that there is lots of other stuff going on between the flag tests, and there is a need for clean-up code (thus don't want to use return), I'd use the same system with a flag:

                                      //Figure out what to do...
                                      bool doSomething = false;
                                      do{
                                      if(!flagA)break;
                                      if(!flagB)break;
                                      if(!flagC)break;
                                      if(!PromptUser())break;
                                      doSomething = true;
                                      }while(0);

                                      //...then do it
                                      if(doSomething)
                                      DoSomething();
                                      else
                                      DoOtherThing();

                                      None

                                      P L 2 Replies Last reply
                                      0
                                      • F FatBuddha

                                        Doh - I was looking at the second code listing. Assuming that there is lots of other stuff going on between the flag tests, and there is a need for clean-up code (thus don't want to use return), I'd use the same system with a flag:

                                        //Figure out what to do...
                                        bool doSomething = false;
                                        do{
                                        if(!flagA)break;
                                        if(!flagB)break;
                                        if(!flagC)break;
                                        if(!PromptUser())break;
                                        doSomething = true;
                                        }while(0);

                                        //...then do it
                                        if(doSomething)
                                        DoSomething();
                                        else
                                        DoOtherThing();

                                        None

                                        P Offline
                                        P Offline
                                        PIEBALDconsult
                                        wrote on last edited by
                                        #32

                                        Still looks like a potentially infinite loop.

                                        F 1 Reply Last reply
                                        0
                                        • G Georgi Atanasov

                                          I have a coding rule - avoid "return" somewhere in the middle of a method, try using local variables to compensate instead. Observing this leads to the following (seen in existing code):

                                          if(flagA)
                                          {
                                          if(flagB)
                                          {
                                          if(flagC)
                                          {
                                          if(PromtUser())
                                          {
                                          DoSomething();
                                          }
                                          else
                                          {
                                          DoOtherThing();
                                          }
                                          }
                                          else
                                          {
                                          DoOtherThing();
                                          }
                                          }
                                          else
                                          {
                                          DoOtherThing();
                                          }
                                          }
                                          else
                                          {
                                          DoOtherThing();
                                          }

                                          How I would have written this is:

                                          if(flagA)
                                          {
                                          if(flagB)
                                          {
                                          if(flagC)
                                          {
                                          if(PromptUser())
                                          {
                                          return;
                                          }
                                          }
                                          }
                                          }

                                          DoOtherThing();

                                          I was wondering how you guys feel about it?

                                          Thanks, Georgi

                                          M Offline
                                          M Offline
                                          Manish K Agarwal
                                          wrote on last edited by
                                          #33

                                          I usualy perfer "goto cleanup" statement (where cleanup is lable inside the function) instead of making code hard to read.

                                          Manish Agarwal manish.k.agarwal @ gmail DOT com

                                          P T 2 Replies Last reply
                                          0
                                          Reply
                                          • Reply as topic
                                          Log in to reply
                                          • Oldest to Newest
                                          • Newest to Oldest
                                          • Most Votes


                                          • Login

                                          • Don't have an account? Register

                                          • Login or register to search.
                                          • First post
                                            Last post
                                          0
                                          • Categories
                                          • Recent
                                          • Tags
                                          • Popular
                                          • World
                                          • Users
                                          • Groups