If / else builds internal and external functions

When I look at the functions of R, I often find the following structure:

f <- function(exp=T) { if (exp) a <- 1 else a <- 2 } f() f(F) 

This will work without errors. But the execution of the function’s internal code causes an error, since R probably assumes that the statement completes after the first assignment a <- 1 and cannot process the following.

 exp=T if (exp) a <- 1 else a <- 2 

Now this makes sense to me, but I still would like to understand why the behavior of the executable code is different when executed inside or outside the function.

+21
r if-statement
Dec 05 '12 at 13:12
source share
2 answers

This is a consequence of using the interactive shell ( REPL ) to run scripts:

After the first branch, the shell saw the full operator, so it assumes that you have entered. Unfortunately, R uses the same shell to interpret scripts, even if they are not entered interactively, so even when you save the if to a file and source it (or pass it to R), you will get an error on the else branch.

But the following will work just fine:

 if (exp) a <- 1 else a <- 2 

Here the interpreter swallows the string and executes it.

In your function, you can assume that the same applies - and it does! However, the function itself begins with an open bracket in your case, so R must read until it finds a suitable closing shape. In contrast, declare this function:

 f <- function (exp) if (exp) a <- 1 else a <- 2 

In R, you can define functions without curly braces around the body. But the above code will not work for the same reason as stand-alone if without braces. In contrast, if I wrote if on a single line, this code would work again.

By the way, your function uses a variable assignment that is not used. You can (should) do the following:

 f <- function (exp) { if (exp) 1 else 2 } 

... and the same when using if inside the shell:

 a <- if (exp) 1 else 2 

because in R, if is an expression that returns a value.

+28
Dec 05
source share

Summary:

There are only two ways for R to know that the else clause belongs to the if clause above:

  • The entire if ... else statement (and possibly other statements) is enclosed in braces;
  • The word else appears on the same line as the end of the if clause.

Proof of:

The above discussion helped me, but I hope I can offer a useful pun. Yes, right, that

 f <- function (exp) if (exp) 1 else 2 

fails with the classic Error: unexpected 'else' in "else" message due to R's failure to continue reading. 1. Two methods were correctly proposed so that R reads past 1:

 f <- function (exp) { if (exp) 1 else 2 } 

and

 f <- function (exp) if (exp) 1 else 2 

But there is a third way that is not mentioned yet --- just move else up the line. So the following also works because R knows what to read in 1:

 f <- function (exp) if (exp) 1 else 2 

I think the key point is to either copy the entire element of the function, or make sure that else appears on the same line as the end of the if clause, so that R knows what to read. This is why a single line solution works. That is why it works:

 f <- function (exp) if (exp) { 1 } else 2 

But this fails:

 f <- function (exp) if (exp) { 1 } else 2 

And using a more standard function body binding, this also works:

 f <- function (exp) { if (exp) { 1 } else 2 } 

But regardless of whether we are building a function, this is a red herring. The only thing that matters is parentheses and the location of else . Thus, these works:

 { if (exp) { 1 } else 2 } if (exp) { 1 } else 2 

but this fails:

 if (exp) { 1 } else 2 

and to demonstrate my statement 1 at the top, this works:

 { x <- 4 if (exp) 1 else 2 } 
+30
Dec 14 '12 at 20:40
source share



All Articles