我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
有人能告诉我发生什么事吗?
答案 0 :(得分:8)
让我专注于
困扰我的是我不能 弄清楚为什么这段代码有效 - 我是 惊讶于它不只是抛出一个 错误。
你为什么这么认为?发生的事情是我们有
y
被分配了一个表达式if() ...
TRUE
或FALSE
y
对我来说似乎很合乎逻辑。
答案 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”而不是。