【问题标题】:Scoping and evaluating functions in RR中的范围和评估函数
【发布时间】:2020-03-12 22:04:59
【问题描述】:

给定以下函数

f <- function(x) {
    g <- function(y) {
            y + z
    }
    z <- 4
    x + g(x)
 }

如果有人在 R 中运行以下代码,为什么答案是 10?我对你如何参与这个问题有点困惑。

z <- 10
f(3)

【问题讨论】:

  • 它正在从函数 env 中获取“z”
  • 函数最后不就是在做4 + 2*x吗?其中 4 = z
  • @markus 是的,但问题是,为什么 z = 4?期望函数定义捕获 z = 10 是合理的。
  • @RobertDodier 它检查第一个环境中的变量,即在函数中,找到它并停止寻找其他地方,即在父环境中。您可以通过重命名函数内的“z”来进行测试,即函数内的z1 &lt;- 4f(3)# [1] 16
  • 或者指定环境即z &lt;- 4; environment(g) &lt;- .GlobalEnv然后调用z &lt;- 10 &gt; f(3) [1] 16

标签: r scoping


【解决方案1】:

R 使用词法作用域,这意味着如果一个对象被引用但未在函数中定义,那么它会在函数被定义的环境中查找,而不是它所在的环境调用。

z 在 g 中被引用但未在 g 中定义,因此它查看定义 g 的环境,即 f 中的环境,因此 g 使用 z = 4。

实际上,在这种情况下,定义 g 的环境与调用 g 的环境相同,因此必须使用 z = 4 的任何方式。如果函数默认使用全局环境来查找函数中未定义的对象,那么它将使用 z = 10 但这不是 R 的工作方式。

让它以不同的方式工作

如果出于某种原因您想强制 g 在调用 f 的环境中查找 z,那么您可以这样做(其中 parent.frame() 指的是调用 f 的环境)。

f2 <- function(x, envir = parent.frame()) {
    g <- function(y) {
            y + with(envir, z)
    }
    z <- 4
    x + g(x)
 }
 z <- 10
 f2(3)
 ## [1] 16

或者我们可以使用y + envir$z,只是它只会在父框架中而不是在其祖先中查找,而with 将在父框架的祖先中查找,如果在父框架中找不到。

另一种方法是像这样更改 g 的环境,以便它在 envir 中查找 g 中未找到的对象:

f3 <- function(x, envir = parent.frame()) {
    g <- function(y) {
            y + z
    }
    environment(g) <- envir
    z <- 4
    x + g(x)
 }
 z <- 10
 f3(3)
 ## [1] 16

【讨论】:

    猜你喜欢
    • 2022-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-31
    • 2018-07-26
    • 2011-04-07
    相关资源
    最近更新 更多