添加两个 if(){}else{} 构造的意外行为

pgl*_*lpm 16 if-statement r

考虑以下 R 输入:

if(TRUE){1}else{0} + if(TRUE){1}else{0}
Run Code Online (Sandbox Code Playgroud)

结果1却是我所期待的2。如果我将每个 if-else 语句括在括号中,

(if(TRUE){1}else{0}) + (if(TRUE){1}else{0})
Run Code Online (Sandbox Code Playgroud)

那么结果是2.

有人可以解释这种行为吗?

MrF*_*ick 14

else直到 R 可以识别表达式的结尾时,该子句才结束。在 R 中,它们{}不是 if/else 语句语法的一部分。可以{}在您想要放置多个语句的任何地方使用。你也可以做

if(TRUE) 1 else 0 + if(TRUE) 1 else 0 
Run Code Online (Sandbox Code Playgroud)

这些{}其实没什么意义。自从

 0 + if(TRUE) 1 else 0 
Run Code Online (Sandbox Code Playgroud)

是一个有效的表达式,R 只是假设您想要子句的所有内容else。通常,R 在完成的表达式后遇到换行符时将结束 else 子句。这意味着

if(TRUE){1}else{0} + 
   if(TRUE){1}else{0}
Run Code Online (Sandbox Code Playgroud)

也会返回相同的值,因为+第一行末尾的 表示还有更多内容,因为有效的表达式不能以 结尾+

lobstr请注意,如果您真的很好奇,您可以在包的帮助下看到表达式如何转换为抽象语法树。

#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 
Run Code Online (Sandbox Code Playgroud)

在这里我们看到一切都嵌套在第一个中if。该公司+不是主要运营商。

正如您所做的那样,您可以使用()or{}显式结束表达式块

{if(TRUE){1}else{0}} + {if(TRUE){1}else{0}}
Run Code Online (Sandbox Code Playgroud)

还请考虑以下情况

x <- 5
if(FALSE) x+1 else x+2
# [1] 7
if(FALSE) x+1 else {x}+{2}
# [1] 7
Run Code Online (Sandbox Code Playgroud)

请注意表达式中的 是如何x+2组合在一起的else。它不会在第一个符号处结束x

  • @pglpm 而且,公平地说,这就是大括号在许多其他语言中的作用。R 的情况并非如此。 (6认同)

dan*_*ooo 6

与决定评估顺序的运算符亲和力有关。与数学一样,括号的优先级高于乘法,比加号和减号的优先级更高。表达式的第二部分永远不会被求值,因此被忽略,结果为 1 例如if(TRUE){1}else{0} + message("I'll never get printed")。包含括号将强制首先分别计算两个部分,然后进行加法运算,得到 2。