什么时候需要在 if 语句周围加括号来控制 R 中公式的顺序?
When do I need parentheses around an if statement to control the sequence of a formula in R?
我试图用一个数除以两个 if 语句的结果之和。出于某种原因,R 在完成第一个 if 语句后忽略两个 if 语句周围的括号,并仅对第一个 if 语句进行除法。在第一个 if 语句周围添加圆括号时,公式会按预期工作。
问题是:为什么会这样?
用 ifelse(y==2,4,1) 替换 if 语句解决了它,以及额外的括号。我很好奇为什么第一次测试给了我意想不到的结果。
x <- 1
y <- 2
z <- 4
test1 <- z/(if(y==2){4}else{1}+if(x==1){4}else{1})
> print(test1)
[1] 1
test2 <- z/((if(y==2){4}else{1})+if(x==1){4}else{1})
> print(test2)
[1] 0.5
我希望 test1 和 test2 的结果都是 0.5
第二个语句 returns z/(4+4),因此 0.5 并且对于第一个语句,它仅评估第一个 if() 子句。证明:
> z/(if(y==2){4}else{1}+if(x==1){4}else{3})
[1] 1
一个很好的问题。来自 R Language Definition:
Computation in R consists of sequentially evaluating statements. Statements, such as x<-1:10 or mean(y), can be separated by either a semi-colon or a new line.
此外,在if
下:
The if/else statement conditionally evaluates two statements. There is a condition which is evaluated and if the value is TRUE then the first statement is evaluated; otherwise the second statement will be evaluated. The if/else statement returns, as its value, the value of the statement that was selected. The formal syntax is
if ( statement1 )
statement2
else
statement3
您遇到的问题是 {1}+if(x==1){4}else{1}
是一个有效的语句,因此 R 将其解释为 statement3。换句话说,从 else
开始,任何内容(在 块 内)直到换行符或分号仅在 if
语句为 FALSE 时才会遇到。
通常情况下,类似
if (y == 2) {
4
} else {
1
}
我们知道在最后一个大括号之后,if 语句已经完成,但表示表达式结束的是 换行符,而不是右大括号。例如,这不会创建 a
if (y == 2) {
4
} else {
1
} -> a
另一种看待它的方式:对我来说,归结为以下事实:
{
用于对语句进行分组,而不是分隔语句。
- 它不是控制流结构或函数定义语法的一部分,就像括号一样,尽管标准用法通常看起来像它。
- 本质上,控制流符号分隔语句,因此优先级低于任何运算符,请参阅:
lobstr::ast(if (TRUE) 1 else 0 + 4)
#> o-`if`
#> +-TRUE
#> +-1
#> \-o-`+`
#> +-0
#> \-4
lobstr::ast(if (TRUE) 1 else {0} + 4)
#> o-`if`
#> +-TRUE
#> +-1
#> \-o-`+`
#> +-o-`{`
#> | \-0
#> \-4
lobstr::ast(if (TRUE) 1 else {0} <- 4) # `<-` has very low precedence amongst operators
#> o-`if`
#> +-TRUE
#> +-1
#> \-o-`<-`
#> +-o-`{`
#> | \-0
#> \-4
lobstr::ast(if (TRUE) 1 else {0} ? 4) # `?` has the lowest precedence amongst operators
#> o-`if`
#> +-TRUE
#> +-1
#> \-o-`?`
#> +-o-`{`
#> | \-0
#> \-4
由 reprex package (v0.3.0)
于 2019-08-19 创建
从这个角度来看,结果并不令人惊讶。
为了进一步说明,使用 OP 的案例:
lobstr::ast(z/(if(y==2){4}else{1}+if(x==1){4}else{1}))
#> o-`/`
#> +-z
#> \-o-`(`
#> \-o-`if`
#> +-o-`==`
#> | +-y
#> | \-2
#> +-o-`{`
#> | \-4
#> \-o-`+`
#> +-o-`{`
#> | \-1
#> \-o-`if`
#> +-o-`==`
#> | +-x
#> | \-1
#> +-o-`{`
#> | \-4
#> \-o-`{`
#> \-1
由 reprex package (v0.3.0)
于 2019-08-19 创建
这个问题引发了关于 R-devel 邮件列表的讨论,
https://r.789695.n4.nabble.com/Documenting-else-s-greed-td4758844.html.
R 处理这个问题的方式令人惊讶,因为在 if/else 和其他一些构造中,左大括号(如果有的话)是要计算的表达式的一部分,而不是语法定界符。特别是,表达式不一定以右大括号结尾。例如,{2} + 3
和 2 + 3
是等价的表达式,所以下面的第一个命令给出 0,而不是 3(第二个命令的结果也是 0,正如预期的那样)。
if(TRUE) 0 else {2} + 3
## [1] 0
if(TRUE) 0 else 2 + 3
## [1] 0
这种混淆主要出现在'if'结构的'else'部分,但不限于此。例如,出于同样的原因({x^2} + 1
等同于 x^2 + 1
),这定义了一个主体为 x^2 + 1
的函数,尽管可能会在下面的第一行出现错误:
f <- function(x){x^2} + 1
f(2)
## [1] 5
我试图用一个数除以两个 if 语句的结果之和。出于某种原因,R 在完成第一个 if 语句后忽略两个 if 语句周围的括号,并仅对第一个 if 语句进行除法。在第一个 if 语句周围添加圆括号时,公式会按预期工作。 问题是:为什么会这样?
用 ifelse(y==2,4,1) 替换 if 语句解决了它,以及额外的括号。我很好奇为什么第一次测试给了我意想不到的结果。
x <- 1
y <- 2
z <- 4
test1 <- z/(if(y==2){4}else{1}+if(x==1){4}else{1})
> print(test1)
[1] 1
test2 <- z/((if(y==2){4}else{1})+if(x==1){4}else{1})
> print(test2)
[1] 0.5
我希望 test1 和 test2 的结果都是 0.5
第二个语句 returns z/(4+4),因此 0.5 并且对于第一个语句,它仅评估第一个 if() 子句。证明:
> z/(if(y==2){4}else{1}+if(x==1){4}else{3})
[1] 1
一个很好的问题。来自 R Language Definition:
Computation in R consists of sequentially evaluating statements. Statements, such as x<-1:10 or mean(y), can be separated by either a semi-colon or a new line.
此外,在if
下:
The if/else statement conditionally evaluates two statements. There is a condition which is evaluated and if the value is TRUE then the first statement is evaluated; otherwise the second statement will be evaluated. The if/else statement returns, as its value, the value of the statement that was selected. The formal syntax is
if ( statement1 ) statement2 else statement3
您遇到的问题是 {1}+if(x==1){4}else{1}
是一个有效的语句,因此 R 将其解释为 statement3。换句话说,从 else
开始,任何内容(在 块 内)直到换行符或分号仅在 if
语句为 FALSE 时才会遇到。
通常情况下,类似
if (y == 2) {
4
} else {
1
}
我们知道在最后一个大括号之后,if 语句已经完成,但表示表达式结束的是 换行符,而不是右大括号。例如,这不会创建 a
if (y == 2) {
4
} else {
1
} -> a
另一种看待它的方式:对我来说,归结为以下事实:
{
用于对语句进行分组,而不是分隔语句。- 它不是控制流结构或函数定义语法的一部分,就像括号一样,尽管标准用法通常看起来像它。
- 本质上,控制流符号分隔语句,因此优先级低于任何运算符,请参阅:
lobstr::ast(if (TRUE) 1 else 0 + 4)
#> o-`if`
#> +-TRUE
#> +-1
#> \-o-`+`
#> +-0
#> \-4
lobstr::ast(if (TRUE) 1 else {0} + 4)
#> o-`if`
#> +-TRUE
#> +-1
#> \-o-`+`
#> +-o-`{`
#> | \-0
#> \-4
lobstr::ast(if (TRUE) 1 else {0} <- 4) # `<-` has very low precedence amongst operators
#> o-`if`
#> +-TRUE
#> +-1
#> \-o-`<-`
#> +-o-`{`
#> | \-0
#> \-4
lobstr::ast(if (TRUE) 1 else {0} ? 4) # `?` has the lowest precedence amongst operators
#> o-`if`
#> +-TRUE
#> +-1
#> \-o-`?`
#> +-o-`{`
#> | \-0
#> \-4
由 reprex package (v0.3.0)
于 2019-08-19 创建从这个角度来看,结果并不令人惊讶。
为了进一步说明,使用 OP 的案例:
lobstr::ast(z/(if(y==2){4}else{1}+if(x==1){4}else{1}))
#> o-`/`
#> +-z
#> \-o-`(`
#> \-o-`if`
#> +-o-`==`
#> | +-y
#> | \-2
#> +-o-`{`
#> | \-4
#> \-o-`+`
#> +-o-`{`
#> | \-1
#> \-o-`if`
#> +-o-`==`
#> | +-x
#> | \-1
#> +-o-`{`
#> | \-4
#> \-o-`{`
#> \-1
由 reprex package (v0.3.0)
于 2019-08-19 创建这个问题引发了关于 R-devel 邮件列表的讨论, https://r.789695.n4.nabble.com/Documenting-else-s-greed-td4758844.html.
R 处理这个问题的方式令人惊讶,因为在 if/else 和其他一些构造中,左大括号(如果有的话)是要计算的表达式的一部分,而不是语法定界符。特别是,表达式不一定以右大括号结尾。例如,{2} + 3
和 2 + 3
是等价的表达式,所以下面的第一个命令给出 0,而不是 3(第二个命令的结果也是 0,正如预期的那样)。
if(TRUE) 0 else {2} + 3
## [1] 0
if(TRUE) 0 else 2 + 3
## [1] 0
这种混淆主要出现在'if'结构的'else'部分,但不限于此。例如,出于同样的原因({x^2} + 1
等同于 x^2 + 1
),这定义了一个主体为 x^2 + 1
的函数,尽管可能会在下面的第一行出现错误:
f <- function(x){x^2} + 1
f(2)
## [1] 5