【问题标题】:Confusion about function arguments in R对 R 中的函数参数感到困惑
【发布时间】:2015-04-24 09:37:06
【问题描述】:

如果我声明一个函数,我可以引用之前的参数:

blah <- function( a=1, b=a ) { print(sprintf("a=%d, b=%d", a, b)) }

输出是:

> blah(10)
[1] "a=10, b=10"
> blah(10, b=30)
[1] "a=10, b=30"

但是,以下方法不起作用:

> blah(a=10, b=a)
Error in sprintf("a=%d, b=%d", a, b) : object 'a' not found

实际上,这或多或少是人们所期望的;那么为什么声明blah &lt;- function(a=10, b=a) 有效呢?为什么这里的作用域与我调用函数时不同?

另外,为什么只有在调用sprintf 时才会出现错误?为什么调用函数时不立即抛出错误?我很困惑。

编辑:

在这里解释我的困惑。当我声明一个函数时,不会评估参数。 R 有惰性求值,变量在需要时进行求值。考虑一下:

> blah <- function( a=1, b=print("foo") ) { print( "So far, so good") ; print( b )  }
>

没有评价。我现在打电话给blah:

> blah()
[1] "So far, so good"
[1] "foo"
[1] "foo"

评估函数中的第一条语句,然后print("foo")。但是,那时, a 就在附近——我们在函数范围内拥有它。那么为什么不评估b=a 呢?当它发生时我们已经在函数中了,a 已经被声明了。

编辑 2:

在你跳到错误的结论之前,请注意,由于 R 的惰性求值,在 R 的函数声明中引用前面的参数是 perfectly fine。我不明白为什么它在函数声明中起作用,但在我调用时不起作用。我并不是说它应该或不应该起作用,只是想知道作用域的基本机制。

【问题讨论】:

  • 您的环境中没有变量“a”。这就是您收到此错误的原因。例如,如果您首先定义a = 150,它就可以工作。函数中的“a”和环境中的“a”是不同的对象。
  • 那么为什么当我声明一个函数时它会起作用?
  • 嗯,确实如此,你自己试试吧。
  • 我不知道怎么做,这就是我问的原因。不过确实如此。此外,它是正确的语法。见johndcook.com/blog/2008/10/16/…
  • 好的,误会请见谅。不过,当我用blah &lt;- function(a=10, b=a) { } 声明我的函数时,a 不在我的环境中,是吗?如果是,它是何时以及如何创建的?

标签: r function arguments


【解决方案1】:

这两个表达式的计算位置有所不同。当您调用函数时,参数会在当前范围内进行评估。当你定义一个函数时,参数是在函数范围内计算的。这通常是您想要的行为。

因此,当您调用该函数时,您应该可以控制传递给该函数的所有值。您不必知道函数内部正在使用哪些变量。通过惰性求值,这种构造也可以工作:

blah <- function( a=1, b=x ) {
   x < a+10
   print(sprintf("a=%d, b=%d", a, b))
}
blah(1)

所以想打电话

blah(1, b=x+5)

更没有意义,因为从技术上讲,您甚至不应该知道函数内部存在 x 变量。

您可以通过此示例看到环境中的差异。这里我们使用parent.frame()来获取调用函数的环境。

myenv <- function() parent.frame()
foo <- function( a=myenv() ) {
    print(environment())
    print(a)
}
foo()
# <environment: 0x10c8b1948>
# <environment: 0x10c8b1948>
foo( a=myenv() )
# <environment: 0x10bd85ad8>
# <environment: R_GlobalEnv>

所以当函数使用默认参数值运行时,它运行在与函数本身相同的环境中。当您显式传递参数时,它会在调用它时的环境中运行(在这种情况下,它是全局环境)。

这意味着在调用函数时设置其他参数值时,不能将函数的参数名称用作变量。

【讨论】:

  • 谢谢,这就是我问题的答案。
【解决方案2】:

当你这样做时:

> blah(a=10, b=a)

你是说:我有一个值10在我的全局环境中,我将它分配给参数a。我有一个变量 a 在我的全局环境中,我将它的值分配给参数b。 变量a 与函数的参数a 完全不同!如果变量a没有定义,你想把它交给函数,R会喊。

你会遇到完全相同的错误:

 > blah(a=10, b=nonExistingVariable)
 Error in sprintf("a=%d, b=%d", a, b) : object 'NonExistingVariable' not found

【讨论】:

  • 我认为最后一行代码比任何解释都更明确,我会缩短我的。
  • 很好,为什么blah &lt;- function(a=1, b=a) 有效?
  • @一月,你在那里定义了一个函数并将它分配给变量blah,你没有使用这个函数。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-12-31
  • 2015-09-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-06
  • 1970-01-01
相关资源
最近更新 更多