Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/72.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
是否在函数中显式调用return_R - Fatal编程技术网

是否在函数中显式调用return

是否在函数中显式调用return,r,R,不久前,R核心团队的Simon Urbanek(我相信)推荐用户在函数结束时显式调用return(他的评论被删除): 相反,他建议: foo = function() { value } 可能在这种情况下,需要: foo = function() { if(a) { return(a) } else { return(b) } } 他的评论揭示了为什么不调用return,除非严格需要是件好事,但这被删除了 我的问题是:为什么调用return不更快或更好,因此更可取?似乎

不久前,R核心团队的Simon Urbanek(我相信)推荐用户在函数结束时显式调用
return
(他的评论被删除):

相反,他建议:

foo = function() {
  value
}
可能在这种情况下,需要:

foo = function() {
 if(a) {
   return(a)
 } else {
   return(b)
 }
}
他的评论揭示了为什么不调用
return
,除非严格需要是件好事,但这被删除了


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

似乎没有
return()
会更快

library(rbenchmark)
x <- 1
foo <- function(value) {
  return(value)
}
fuu <- function(value) {
  value
}
benchmark(foo(x),fuu(x),replications=1e7)
    test replications elapsed relative user.self sys.self user.child sys.child
1 foo(x)     10000000   51.36 1.185322     51.11     0.11          0         0
2 fuu(x)     10000000   43.33 1.000000     42.97     0.05          0         0
库(rbenchmark)

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

R文档中没有做出这种假设的陈述。
主页“函数”显示:

function( arglist ) expr
return(value)
不打电话返回是否更快?

function()
return()
都是基本函数,
function()
本身即使不包含
return()
函数也会返回上一次计算的值

 if(a) {
   return(a)
 } else {
   return(b)
 }
用最后一个值作为参数调用
return()
作为
基本体('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
这取决于程序员的策略和编程风格他使用什么风格,他可以使用no return(),因为这不是必需的

R核心程序员使用这两种方法,即使用和不使用显式return(),因为可以在“base”函数源中找到

很多情况下,只使用return()(无参数)在情况下返回NULL以辅助停止函数

 if(a) {
   return(a)
 } else {
   return(b)
 }
由于标准用户或使用R的分析师看不到真正的区别,因此不清楚它是否更好

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


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

如果每个人都同意

  • return
    在函数体的末尾不是必需的
  • 不使用
    return
    稍微快一点(根据@Alan的测试,4.3微秒比5.1微秒)
  • 我们是否应该在函数结束时停止使用
    return
    ?我当然不会,我想解释一下原因。我希望听到其他人是否同意我的观点。如果这不是对OP的直截了当的回答,而更像是一个冗长的主观评论,我道歉

    我不使用
    return
    的主要问题是,正如Paul指出的,函数体中还有其他地方可能需要它。如果你被迫在函数的中间使用<代码>返回<代码>某个地方,为什么不让所有的代码>返回< /COD>语句显式?我讨厌前后矛盾。而且我认为代码读起来更好;可以扫描函数,轻松查看所有退出点和值

    保罗举了这个例子:

    foo = function() {
     if(a) {
       return(a)
     } else {
       return(b)
     }
    }
    
    不幸的是,有人可能会指出,它可以很容易地改写为:

    foo = function() {
     if(a) {
       output <- a
     } else {
       output <- b
     }
    output
    }
    
    foo=function(){
    如果(a){
    
    输出这是一个有趣的讨论。我认为@flodel的例子非常好。但是,我认为它说明了我的观点(并且@koshke在评论中提到了这一点),即
    return
    在使用命令式而不是函数式编码风格时是有意义的

    我不是要详细说明这一点,但我会像这样重写
    foo

    foo = function() ifelse(a,a,b)
    
    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.
    }
    
    f = function (a, b) {
        if (precondition(a)) calculation(b)
    }
    
    函数样式避免状态更改,例如存储
    输出的值。在这种样式中,
    返回
    是不合适的;
    foo
    看起来更像一个数学函数

     if(a) {
       return(a)
     } else {
       return(b)
     }
    
    我同意@flodel的观点:在
    bar
    中使用一个复杂的布尔变量系统将变得不那么清晰,当你有
    return
    时,它将变得毫无意义。
    bar
    语句之所以如此易于
    return
    语句,是因为它是以命令式编写的。实际上,布尔变量代表“状态”功能性风格中避免的变化

    用函数式重写
    bar
    确实很困难,因为它只是伪代码,但其思想是这样的:

    foo = function() ifelse(a,a,b)
    
    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.
    }
    
    f = function (a, b) {
        if (precondition(a)) calculation(b)
    }
    
    在函数式中,返回的值自然地落在函数的末尾。同样,它看起来更像一个数学函数

     if(a) {
       return(a)
     } else {
       return(b)
     }
    
    < GSee >在<代码>中勾勒出的警告,IFE/<代码>肯定是有趣的,但我不认为他们是在劝阻函数的使用。事实上,<代码> IFOR/<代码>具有自动矢量化功能的优点。例如,考虑一个稍微修改的版本<代码> FoO >:

    foo = function(a) { # Note that it now has an argument
     if(a) {
       return(a)
     } else {
       return(b)
     }
    }
    
    length(a)
    为1时,此函数可以正常工作。但是如果使用
    ifelse

    foo = function (a) ifelse(a,a,b)
    

    现在
    foo
    可以在
    a
    的任何长度上工作。事实上,当
    a
    是一个矩阵时,它甚至可以工作。返回与
    test
    形状相同的值是一个有助于矢量化的功能,而不是一个问题。

    如果在末尾添加额外的语句,则不在末尾显式地添加“return”e方法结束时,突然返回值错误:

    foo <- function() {
        dosomething()
    }
    
    我们希望我们的代码返回
    dosomething()
    的值,但它不再返回

    通过显式返回,这一点变得非常明显:

    foo <- function() {
        return( dosomething() )
        dosomething2()
    }
    

    foo我认为
    return
    是一种技巧。一般来说,函数中最后一个表达式的值会变成函数的值
    ugly <- function(species, x, y){
       if(length(species)>1) stop("First argument is too long.")
       if(species=="Mickey Mouse") return("You're kidding!")
       ### do some calculations 
       if(grepl("mouse", species)) {
          ## do some more calculations
          if(species=="Dormouse") return(paste0("You're sleeping until", x+y))
          ## do some more calculations
          return(paste0("You're a mouse and will be eating for ", x^y, " more minutes."))
          }
       ## some more ugly conditions
       # ...
       ### finally
       return("The end")
       }
    
    getout <- TRUE 
    # if getout==TRUE then the value of EXP, LOC, and FUN will be "OUTTA HERE"
    # .... if getout==FALSE then it will be `3` for all these variables    
    
    EXP <- eval(expression({
       1
       2
       if(getout) return("OUTTA HERE")
       3
       }))
    
    LOC <- local({
       1
       2
       if(getout) return("OUTTA HERE")
       3
       })
    
    FUN <- (function(){
       1
       2
       if(getout) return("OUTTA HERE")
       3
       })()
    
    identical(EXP,LOC)
    identical(EXP,FUN)
    
    foo <- function() {
        if (a) return(a)       
        b     
    }
    
    # Add one to the result
    result = x + 1
    
    f = function (a, b) {
        if (! precondition(a)) return() # same as `return(NULL)`!
        calculation(b)
    }
    
    sign = function (num) {
        if (num > 0) {
            1
        } else if (num < 0) {
            -1
        } else {
            0
        }
    }
    
    f = function (a, b) {
        if (precondition(a)) calculation(b)
    }
    
    save_results = function (results, file) {
        # … code that writes the results to a file …
        invisible()
    }
    
    function(){
      #do stuff
      ...
      abcd
    }
    
    function(){
      #do stuff
      ...
      return(abdc)
    }