小编典典

是否在函数中显式调用 return

all

不久前,因为我建议用户return在函数结束时显式调用(尽管他的评论已被删除):

foo = function() {
  return(value)
}

相反,他建议:

foo = function() {
  value
}

可能在这种情况下,它是必需的:

foo = function() {
 if(a) {
   return(a)
 } else {
   return(b)
 }
}

他的评论阐明了为什么return除非非常需要才打电话是一件好事,但这已被删除。

我的问题是:为什么不调用return更快或更好,因此更可取?


阅读 60

收藏
2022-06-16

共1个答案

小编典典

问题是:为什么不(明确地)调用 return 更快或更好,因此更可取?

R 文档中没有声明做出这样的假设。
主页“功能”说:

function( arglist ) expr
return(value)

不调用return会更快吗?

function()和都是return()原始函数,function()即使不包含函数,它本身也会返回最后的评估值return()

return()将最后一个值作为参数调用.Primitive('return')将完成相同的工作,但需要再调用一次。这样这个(通常)不必要的.Primitive('return')调用会消耗额外的资源。然而,简单的测量表明产生的差异非常小,因此不能成为不使用显式返回的原因。下图是根据以这种方式选择的数据创建的:

bench_nor2 <- function(x,repeats) { system.time(rep(
# without explicit return
(function(x) vector(length=x,mode="numeric"))(x)
,repeats)) }

bench_ret2 <- function(x,repeats) { system.time(rep(
# with explicit return
(function(x) return(vector(length=x,mode="numeric")))(x)
,repeats)) }

maxlen <- 1000
reps <- 10000
along <- seq(from=1,to=maxlen,by=5)
ret <- sapply(along,FUN=bench_ret2,repeats=reps)
nor <- sapply(along,FUN=bench_nor2,repeats=reps)
res <- data.frame(N=along,ELAPSED_RET=ret["elapsed",],ELAPSED_NOR=nor["elapsed",])

# res object is then visualized
# R version 2.15

功能经过时间比较

上图在您的平台上可能略有不同。根据测量数据,返回对象的大小不会造成任何差异,重复次数(即使按比例放大)只会产生很小的差异,这在实际数据和实际算法中无法计算或使您的脚本运行得更快。

不调用return会更好吗?

Return是一个很好的工具,可以清楚地设计例程应该结束的代码“叶子”,跳出函数并返回值。

# here without calling .Primitive('return')
> (function() {10;20;30;40})()
[1] 40
# here with .Primitive('return')
> (function() {10;20;30;40;return(40)})()
[1] 40
# here return terminates flow
> (function() {10;20;return();30;40})()
NULL
> (function() {10;20;return(25);30;40})()
[1] 25
>

这取决于程序员的策略和编程风格,他使用什么风格,他可以使用 no return() 因为它不是必需的。

R核心程序员使用这两种方法,即。有和没有明确的 return() 因为可以在“基本”函数的来源中找到。

很多时候,在有条件地停止函数的情况下,只使用 return()(无参数)返回 NULL。

目前尚不清楚它是否更好,因为使用 R 的标准用户或分析师看不到真正的区别。

我的观点是,问题应该是: 使用来自 R 实现的显式返回是否有任何危险?

或者,也许更好的是,编写函数代码的用户应该总是问:在函数代码 使用显式返回(或将要返回的对象作为代码分支的最后一叶)有什么影响?

2022-06-16