这是一个有趣的讨论。我认为@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
可能无济于事,但引导他们使用实用的风格会有所收获。
@Paul return
在命令式中是必需的,因为您经常想在循环中的不同点退出该函数。功能样式不使用循环,因此不需要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
是有助于矢量化的功能,这不是问题。
return
即使在最后一个示例中也没有必要。删除return
可能会使它更快一些,但是在我看来,这是因为R被认为是一种函数式编程语言。