这是一个有趣的讨论。我认为@flodel 的例子非常好。但是,我认为它说明了我的观点(@koshke 在评论中提到了这一点),当您使用命令式而不是函数式编码风格时,这return
是有道理的。
不是要强调这一点,但我会这样重写foo
:
foo = function() ifelse(a,a,b)
函数式风格避免了状态变化,比如存储output
. 在这种风格return
下,显得格格不入;foo
看起来更像一个数学函数。
我同意@flodel:使用复杂的布尔变量系统bar
会不太清楚,当你有return
. 使陈述bar
如此顺从的return
原因是它是以命令式的风格编写的。事实上,布尔变量代表了功能风格中避免的“状态”变化。
用函数式重写真的很难bar
,因为它只是伪代码,但想法是这样的:
e_func <- function() do_stuff
d_func <- function() ifelse(any(sapply(seq(d),e_func)),2,3)
b_func <- function() {
do_stuff
ifelse(c,1,sapply(seq(b),d_func))
}
bar <- function () {
do_stuff
sapply(seq(a),b_func) # Not exactly correct, but illustrates the idea.
}
循环将while
是最难重写的,因为它是由状态更改控制的a
。
调用造成的速度损失return
可以忽略不计,但通过避免return
和重写函数式风格所获得的效率往往是巨大的。告诉新用户停止使用return
可能无济于事,但引导他们使用实用风格会有所收获。
@Paulreturn
在命令式风格中是必需的,因为您经常希望在循环中的不同点退出函数。函数式风格不使用循环,因此不需要return
. 在纯函数式风格中,最终调用几乎总是所需的返回值。
在 Python 中,函数需要一个return
语句。但是,如果您以函数式风格编写函数,则可能只有一个return
语句:在函数的末尾。
使用另一个 StackOverflow 帖子中的示例,假设我们想要一个函数,TRUE
如果给定中的所有值x
都具有奇数长度,则该函数会返回。我们可以使用两种样式:
# Procedural / Imperative
allOdd = function(x) {
for (i in x) if (length(i) %% 2 == 0) return (FALSE)
return (TRUE)
}
# Functional
allOdd = function(x)
all(length(x) %% 2 == 1)
在函数式风格中,要返回的值自然落在函数的末尾。同样,它看起来更像是一个数学函数。
@GSee 中概述的警告?ifelse
绝对很有趣,但我不认为他们试图阻止使用该功能。实际上,ifelse
具有自动矢量化功能的优势。例如,考虑一个稍微修改过的版本foo
:
foo = function(a) { # Note that it now has an argument
if(a) {
return(a)
} else {
return(b)
}
}
这个函数在length(a)
为 1 时工作正常。但如果你foo
用ifelse
foo = function (a) ifelse(a,a,b)
现在foo
适用于任何长度的a
. 事实上,它甚至可以在a
是一个矩阵时起作用。test
返回一个与矢量化具有相同形状的值,这不是问题。