从if-else块分配值(它是如何工作的?)

Ric*_*ton 0 if-statement r

最近发现你可以通过if-else块有条件地分配一个值.

y <- if(condition) 1 else 2
Run Code Online (Sandbox Code Playgroud)

我意识到这个用例是有限的:如果你有矢量化代码,你会使用该ifelse函数.有一个性能优势:if-else运行速度比ifelse我机器上的标量情况快35倍(尽管你需要多次调用它才能发现差异很大).

困扰我的是我无法弄清楚为什么这段代码有效 - 我很惊讶它不仅仅是抛出一个错误.

另一个例子表明,如果块的行为与函数类似 - 它们会自动返回块中的最后一个值(尽管您不能return在其中使用语句).

y <- if(TRUE) 
{
   y <- 3
   4
}    # y is 4
Run Code Online (Sandbox Code Playgroud)

基于此,我猜想当你输入if块时可能会创建另一个环境,但事实并非如此.

if(TRUE) sys.frames()    # NULL
Run Code Online (Sandbox Code Playgroud)

有人能告诉我引擎盖下发生了什么事吗?

Dir*_*tel 8

让我关注一下

困扰我的是我无法弄清楚为什么这段代码有效 - 我很惊讶它不仅仅是抛出一个错误.

你为什么这么认为?会发生什么,我们有

  1. y 分配表达
  2. 表达式是if if() ...
  3. 导致一个TRUEFALSE一个测试
  4. 导致两个分支中的任何一个进入
  5. 导致相应的代码被评估
  6. 导致其最终价值是右侧的价值
  7. 导致将此值分配给 y

对我来说似乎很合乎逻辑.


rcs*_*rcs 5

控制结构if(....) ... else ...等同于函数调用,并使用相关的(延迟求值的)子表达式作为参数:

`if`(TRUE, "yes", "no")
Run Code Online (Sandbox Code Playgroud)

基本上,if是一个特殊的原始函数:

R> sapply(ls("package:base", all=TRUE), function(x) is.primitive(get(x)))["if"]
  if 
TRUE 
R> sapply(ls("package:base", all=TRUE), function(x) typeof(get(x)))["if"]
       if 
"special" 
Run Code Online (Sandbox Code Playgroud)

R语言定义手册中的相关章节(第3.2.1节)说:

因为if/else语句与其他语句相同,所以可以分配它们的值.以下两个例子是等效的.

R> if( any(x <= 0) ) y <- log(1+x) else y <- log(x)
R> y <- if( any(x <= 0) ) log(1+x) else log(x)
Run Code Online (Sandbox Code Playgroud)