Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

R: unexpected behaviour adding two if(){}else{} constructs

Tags:

r

if-statement

Consider the following R input:

if(TRUE){1}else{0} + if(TRUE){1}else{0}

The result is 1, but I was expecting 2. If I enclose each if-else statement in parentheses,

(if(TRUE){1}else{0}) + (if(TRUE){1}else{0})

then the result is 2.

Can someone explain this behaviour?

like image 623
pglpm Avatar asked Dec 08 '21 08:12

pglpm


2 Answers

The else clause doesn't end till R can identify the end of the expression. In R the {} aren't part of the syntax for if/else statements. The {} can be used anywhere you want to possibly put multiple statements. You can also do

if(TRUE) 1 else 0 + if(TRUE) 1 else 0 

The {} aren't really meaningful. And since

 0 + if(TRUE) 1 else 0 

is a valid expression, R just assumes you wanted all of that for your else clause. Normally R will end the else clause when it encounters a newline after a completed expression. This means that

if(TRUE){1}else{0} + 
   if(TRUE){1}else{0}

will also return the same value because the + at the end of the first line indicates that there's more to come because a valid expression can't end in +.

Note you can see how the expression is turned into the abstract syntax tree with the help of the lobstr package if you are really curious.

#lobstr::ast(if(TRUE){1}else{0} + if(TRUE){1}else{0})
o-`if` 
+-TRUE 
+-o-`{` 
| \-1 
\-o-`+` 
  +-o-`{` 
  | \-0 
  \-o-`if` 
    +-TRUE 
    +-o-`{` 
    | \-1 
    \-o-`{` 
      \-0 

Here we see that everything is nested in the first if. The + is not the main operator.

As you've done, you can use () or {} to end the expression blocks explicitly

{if(TRUE){1}else{0}} + {if(TRUE){1}else{0}}

Consider also the case of

x <- 5
if(FALSE) x+1 else x+2
# [1] 7
if(FALSE) x+1 else {x}+{2}
# [1] 7

Note how the x+2 is taken all together for the else expression. It doesn't end at the first symbol x.

like image 115
MrFlick Avatar answered Oct 25 '22 00:10

MrFlick


Is has something to to with operator affinity which determines the order of evaluation. Like math, parenthesis have a higher priority than multiplications with have a higher priority than plus and minus. The second part of the expression will never get evaluated and thus ignored resulting in 1 e.g. if(TRUE){1}else{0} + message("I'll never get printed"). Including the parenthesis will force to first evaluate both parts seperatley and then do the plus resulting in 2.

like image 34
danlooo Avatar answered Oct 25 '22 01:10

danlooo