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
给定以下函数
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