R 中的作用域和评估函数

Scoping and evaluating functions in R

给定以下函数

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

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

z <- 10
f(3)

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