【问题标题】:R function with no return value没有返回值的R函数
【发布时间】:2014-02-27 17:52:49
【问题描述】:

我正在帮助我的一个朋友编写他的一些代码。我不知道如何解释这种奇怪的行为,但我可以告诉他他的函数没有明确返回任何东西。这是一个最小的可重现示例:

derp <- function(arg){
  arg <- arg+3
}

data <- derp(500)
data
#[1] 503
derp(500)
#nothing outputs
class(derp(500))
#[1] "numeric"

有没有可以用谷歌搜索的名称?为什么会这样?为什么在对 derp() 的调用完成后 arg 没有被销毁?

【问题讨论】:

  • 试试z &lt;- derp(500); z(derp(500))。另外,看看如果你没有在你的函数源中分配arg + 3然后使用这个函数会发生什么。
  • 函数末尾没有arg,你就不会打印任何东西。试试(derp(500))

标签: r function


【解决方案1】:

您需要了解函数返回一个值和打印该值之间的区别。默认情况下,函数返回最后一个表达式的值,在这种情况下是赋值

arg <- arg + 3

(请注意,在 R 中,赋值是一个返回值的表达式,在本例中为已分配的值。)这就是为什么 data &lt;- derp(500) 导致 data 包含 503。

但是,默认情况下,返回的值不会打印到屏幕上,除非您将函数的最终表达式隔离在自己的行中。这是 R 中的怪癖之一。因此,如果您想查看该值:

derp <- function(arg)
{
    arg <- arg + 3
    arg
}

或者只是

derp <- function(arg)
arg + 3

【讨论】:

  • 我不同意你的说法“返回值默认不打印到屏幕上”。它是默认打印的。问题是分配将可见性设置为 FALSE 以使其不显示。这也是为什么当您执行a &lt;- 3 时您也看不到“3”被打印出来的原因。查看withVisible(3)withVisible(a &lt;- 3) 的比较
  • @Dason 甚至 a &lt;- 3(a &lt;- 3)
  • 好的,很好的解释。我想这比奇怪更多余。它似乎只是链接分配 a
  • @Dason ...“除非您将函数的最终表达式隔离在自己的行中”
【解决方案2】:

arg 变量正在被销毁。 R 中的函数将返回函数中执行的最后一条语句的值,除非显式调用 return 语句。

在您的情况下,arg 的副本是您的函数的返回值。示例:

alwaysReturnSomething = function()
{
  x = runif(1)
  if(x<0.5) 20  else 10
}
> for(x in 1:10) cat(alwaysReturnSomething())
20202020102010101020

或:

alwaysReturnSomething <- function(){}
> z=alwaysReturnSomething()
> z
NULL

【讨论】:

    【解决方案3】:

    这是一种奇怪的行为。

    基本上derp(),如果你分配derp()的输出,它会返回,如果你不分配结果,derp()不会返回。这是因为赋值函数 (&lt;-) 使用 invisible() 函数返回。请参阅 Make a function return silently 了解其工作原理。

    您可以使用derp2 看到相同的行为:

    derp2 <- function(arg) {
      invisible(arg + 3)
    }
    derp2(3)
    # nothing
    b <- derp2(3)
    b
    # 6
    

    【讨论】:

      【解决方案4】:

      我经常在包含在一些一致性检查中的函数的开头使用return(NULL),例如是否会覆盖输出文件。例如

      some_function <- function(output_filename, overwrite = FALSE) {
        if (file.exists(output_filename)) {
          if (!overwrite) {
            return(NULL)
          }
        }
      }
      

      在这种情况下,调用 some_function("file.path", overwrite = FALSE) 将返回 NULL。您可以通过将返回修改为:

      ...
      return(invisible(NULL))
      ...
      

      【讨论】:

        【解决方案5】:

        如果你想要一个函数来改变全局环境中变量的值,你可以使用&lt;&lt;-操作符,但是你仍然需要写出全局环境中变量的确切名称

        derp <- function(arg){
          arg <- arg+3
          b<<-3
        }
        

        试试看并致电b

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2017-06-25
          • 2011-06-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多