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

时间:2009-12-02 15:27:59

标签: r if-statement

recently discovered您可以使用if-else块有条件地分配值。

y <- if(condition) 1 else 2

我意识到这个用例是有限的:如果你有矢量化代码,你可以使用ifelse函数。有一个性能优势:if-else在我的计算机上的标量情况下比ifelse运行速度快35倍(尽管你需要多次调用它才能注意到差异)。

让我感到烦恼的是,我无法理解为什么这段代码有效 - 我很惊讶它不仅仅会引发错误。

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

y <- if(TRUE) 
{
   y <- 3
   4
}    # y is 4

基于此,我猜测当你输入if块时可能会创建另一个环境,但似乎并非如此。

if(TRUE) sys.frames()    # NULL

有人能告诉我发生什么事吗?

4 个答案:

答案 0 :(得分:8)

让我专注于

  

困扰我的是我不能   弄清楚为什么这段代码有效 - 我是   惊讶于它不只是抛出一个   错误。

你为什么这么认为?发生的事情是我们有

  1. y被分配了一个表达式
  2. 该表达式为if if() ...
  3. 导致测试中的TRUEFALSE
  4. 导致输入两个分支中的任何一个
  5. 导致评估相应的代码
  6. 导致其最终价值为右侧的价值
  7. 导致将此值分配给y
  8. 对我来说似乎很合乎逻辑。

答案 1 :(得分:5)

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

`if`(TRUE, "yes", "no")

基本上,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" 

R Language Definition manual中的相关部分(第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)

答案 2 :(得分:3)

关于问题的第二部分 - {}用于对表达式进行分组,它与函数定义不同。正如您可以阅读help("Paren")

  

对于‘{’,评估最后一个表达式的结果。

但所有表达式都在当前环境中进行评估:

y <- if (TRUE) {
    print(paste("Current frame:",sys.nframe()))
    y <- 3
    z <- 5
    4
}
# [1] "Current frame: 0"
# result:
y # [1] 4
z # [1] 5

# compare to use function:
v <- if(TRUE) (function(){      
    print(paste("Current frame:",sys.nframe()))
    v <- 3
    w <- 5
    4
})()
# [1] "Current frame: 1"
v # [1] 4
w # Error: object 'w' not found

结论是块的行为不像函数

编辑: 如果您想使用块作为函数,可以使用local

a <- if (TRUE) local({
    print(paste("Current frame:",sys.nframe()))
    a <- 3
    b <- 5
    4
})
# [1] "Current frame: 6"
a # [1] 4
b # Error: object 'b' not found

然后你也可以使用return

a <- if (TRUE) local({
    print(paste("Current frame:",sys.nframe()))
    a <- 3
    b <- 5
    return(7)
    4
})
# [1] "Current frame: 6"
a # [1] 7
b # Error: object 'b' not found

答案 3 :(得分:2)

它并不是很深 - 很多语言都使用“val = x?y:z”构造。在R中,它只是折叠成if / else结构,所以你写“val = if(x)y else z”而不是。