Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Something like "return"

    Is there something like return in Stata? I find myself writing overnested loops and wonder if I can circumvent that.

    Something like this
    Code:
    do some test
    if x {
       return
    }
    
    do some other test
    if x {
       return
    }
    
    ...

    RIght now my code looks something like this
    Code:
    do some test
    if x {
       bla
    }
    else {
         do some other test
         if x {
         blbla
        }
    }
    ...
    which blows up the more test we do.



  • #2
    One way to avoid many levels of nesting could be to have a `skip' local which can be set to one. Then all the other conditions need a `skip'==0

    Comment


    • #3
      I'm not really sure what you're trying to do here with the return keyword. break out of a loop? exit a code block? exit a program?

      You mention loops in the OP, but don't show any loops in your example code, which is a little confusing. If you want to break out of a loop, you can use:

      Code:
      continue, break
      which works the same way you might expect the break keyword to work in many other languages.

      Or do you mean nested conditional statements rather than nested loops? There are a few common techniques for reducing the number of nested conditional statements you might need to test. For example, if you're not worried about the efficiency of testing multiple conditions up front, you could write your conditional statement like so:

      Code:
      local condition1 = do some test
      local condition2 = do some other test
      if condition1 {
         do some stuff
      }
      else if condition2 {
          do some other stuff
      }
      else {
         di "No tests passed"
      }  
      Theoretically, if you really want to scale this kind of thing, the "right" way to do this is with a data structure. You might imagine storing all of your tests in a list, and all of the code you want to do conditional on the test in another list of equal length. Go through the conditions one by one and run the condition until one of them passes. Then get the corresponding code to run when the test passes by getting the element in the other list at the same index. Run the corresponding code.

      Stata does indeed have a return keyword. It is used to store data in the global environment before exiting a program. I'm not sure, but I don't think it will not function like a goto the way it will in other languages. In other languages you might return within a condition to exit a function. Are you trying to do something like that here, but inside of a program?
      Last edited by Daniel Schaefer; 07 Sep 2023, 10:12.

      Comment


      • #4
        This is the implementation I might go with for the theoretical "data structure" solution I describe in #3:

        Code:
        local constant = 3
        local test1 = "`constant' == 1"
        local test2 = "`constant' == 2"
        local test3 = "`constant' == 3"
        local test4 = "`constant' == 4"
        
        local exe1 = "di 1"
        local exe2 = "di 2"
        local exe3 = "di 3"
        local exe4 = "di 4"
        
        forv i = 1/4{
            if `test`i'' {
                `exe`i''
                continue, break
            }
        }
        Note that once any test passes, we break out of the loop, so subsequent conditions won't be tested. I get the impression from the OP that is the behavior you want. This is not quite as convenient as a list of lambda functions like you might see in R or python, but it gets the job done. But now, let's say you want to scale this up so that you can execute multiple lines. There are a few ways to do this, but after some thought, I landed on programs for encapsulating multiple lines.

        Code:
        local constant = 3
        local test1 = "`constant' == 1"
        local test2 = "`constant' == 2"
        local test3 = "`constant' == 3"
        local test4 = "`constant' == 4"
        
        
        quietly capture program drop exe1
        program exe1
        display "constant is equal to 1"
        display "here is a second line"
        display "here is a third line"
        end
        
        quietly capture program drop exe2
        program exe2
        display "constant is equal to 2"
        display "here is a second line"
        display "here is a third line"
        end
        
        quietly capture program drop exe3
        program exe3
        display "constant is equal to 3"
        display "here is a second line"
        display "here is a third line"
        end
        
        quietly capture program drop exe4
        program exe4
        display "constant is equal to 4"
        display "here is a second line"
        display "here is a third line"
        end
        
        forv i = 1/4{
            if `test`i'' {
                exe`i'
                continue, break
            }
        }

        Comment


        • #5
          I notice I have a double negative in #3. That should read:

          but I think it will not function like a goto
          Sorry for any confusion.

          Comment


          • #6
            Thanks for your reply and sorry that I was unclear. I am generally interested how to reduce nested if conditions, so your answer is very helpful, thank you. In the application I am thinking about I have multiple tests, think about

            Code:
            su `var'
            if r(sd)==0
            type of statements, and if the test test fails (or rather accepted in the example) then I want to immediately exit the loop.

            Comment


            • #7
              I replied too early. #4 is indeed what I was looking for.

              Comment

              Working...
              X