Home  /  Resources & Support  /  FAQs  /  Stata 7: Nested for commands
Note: This FAQ is for users of Stata 7. It is not relevant for more recent versions.

Stata 7: Why do some nested for commands produce an error?

Title   Stata 7: Nested for commands
Author Kenneth Higbee, StataCorp

The for command's syntax uses the backslash ("\") in two different ways. One way is as a separator for multiple lists in the first part of the syntax (the part before the colon). The other way, the backslash is used as a separator for multiple commands to be executed during the loop (the part of the syntax after the colon).

That the backslash has two different meanings depending on its position leads to an ambiguity in interpretation with certain nested for commands. This is why some nested for commands produce an error.

Here is what for does:

  • Finds the first colon and interpret what precedes it (call it part1), as setting up the list (or lists) of values to be looped over, and ALL of what follows the colon (call it part2), as the command (or commands) to be executed in the loop.
  • part1 is then examined for backslashes ("\") to determine how many lists to set up and how to set them up. These looping lists are created.
  • If there is more than one looping list, it is confirmed that each has the same number of elements so that they may be substituted in parallel into part2.
  • part2 (ALL that follows the colon) is now examined for backslashes to determine which and how many commands are to be executed as the for loop is implemented.

At this step, if there is another (nested) for command in part2 that also uses the backslash as part of its syntax, then all of these backslashes are interpreted as separators of commands for the first for loop. This is what causes the error.

Here is a nested for command example that causes no ambiguity because there are no backslashes used.

        . for A in num 1/2, noh : for B in num 1/3, noh : display "A,B"
        1,1
        1,2
        1,3
        2,1
        2,2
        2,3

The noh above is shorthand for the noheader option that suppresses all the extra information for usually presents before executing the command(s) at each loop iteration.

Also

        . for A in num 1/2 \ B in num 5/6, noh: for X in num 1/3, noh: disp "A,B,X"
        1,5,1
        1,5,2
        1,5,3
        2,6,1
        2,6,2
        2,6,3

has no ambiguity because all of the backslashes (only one in this case) occur before the first colon.

However,

        . for A in num 1/2 : for X in num 1/3 \ Y in num 7/9 : di "A,X,Y"

        ->  for X in num 1/3
        invalid syntax
        r(198);

does not work. Here is why:

  • part1 is
      A in num 1/2
  • part2 is
      for X in num 1/3 \ Y in num 7/9 : di "A,X,Y"

part2 is examined for backslashes that signal the division between multiple commands. It finds one backslash and sets up two commands:

  • cmd1 is
           for X in num 1/3
  • cmd2 is
           Y in num 7/9 : di "A,X,Y"

neither of which are valid commands. for now tries to execute the loop by setting the "A"'s to 1. cmd1 and cmd2 then become

  • cmd1 is
           for X in num 1/3
  • cmd2 is
           Y in num 7/9 : di "1,X,Y"

and then cmd1 is executed, producing the error message we see.

You might be tempted to ask why Stata isn't smart enough to see that the backslash does not belong with the first for loop? For simple examples like the one above, it is possible to think of algorithms to determine the context of the backslash (for example, searching for the word "for" in part2 to determine if there is nesting or searching for multiple colons). However, in a general setting, these methods will not work given the current syntax of for. For instance, "for" can appear as a name in some other context (for example, as a variable name or abbreviation of a variable name), and colons are also used by other commands (like by).

When you need the functionality of nested for commands, you can always turn to nested while loops instead.

        for A in num 1/2 : for X in num 1/3 \ Y in num 7/9 : di "A,X,Y"

This is incorrect, but it can be rewritten as

        local A 1
        while `A' <= 2 {
            local X 1
            local Y 7
            while `X' <= 3 {
                di "`A',`X',`Y'"
                local X = `X' + 1
                local Y = `Y' + 1
            }
            local A = `A' + 1
        }

which produces

        1,1,7
        1,2,8
        1,3,9
        2,1,7
        2,2,8
        2,3,9

The motto is nested for commands that use backslashes after the first colon will not work due to the dual purposes served by the backslash in the for command syntax. Instead, use the foreach or forvalues commands for these cases.