Written by Peter Rosenmai on 17 Jan 2014.
I present here what I consider to be a fiendishly weird quirk in R's code parser.
Okay, so what do you expect the following code to do?
Run it and you'll see that it prints the number 1, as you would expect.
Okay, now what happens when you remove the top-level if block?
If you thought that running the above code snippet within an R script would also print the number 1, you're only half right. It prints 1 and spits out this error:
Similarly, this prints 1:
But this give that same error:
What on earth is going on?
This apparent craziness happens because of the way R's parser works. It reads code in line by line until it gets a complete and executable block of code; it then executes that code and moves on to the next block. So it reads (x){print(1)} as a complete and legal statement, executes it… and then can't work out what to do with the else {print(0)} that follows it. This is just like what would happen if you had entered the code in interactive mode. You'd expect the first line to execute without trouble, but the second line to give an error.
However, when you place those lines within a code block, R reads all the code within the block before executing it. In this case, R has a chance to see that the else statement is paired with the if statement that precedes it—and no error is thrown.
So, if you want to run an if-else statement pair at the topmost level of your code, you can surround it with curly braces. This forces R to read it in as an entire code block:
Alternatively, you can move the closing brace of your if statement onto the same line as your else statement. This forces R to read in that second line before executing the if statement—and to realise that the else statement accompanies the if statement. For example:
My jaw dropped when I first encountered this quirk in the R parser. It makes sense when you think of the code as being interpreted and executed line by line as the parser reads it in (rather than being read in all in one piece, being interpreted and then executed). But however one spins it, this is a pretty strange bit of parser voodoo. Definitely one to watch out for.