do.call 的环境选项如何工作?

Cla*_*lke 4 r

国家的文件do.call

如果quoteFALSE,默认值,则对参数求值(在调用环境中,而不是在 中envir)。

这句话向我暗示, when quote = FALSE,指定envir没有区别。然而,事实并非如此,事实上我遇到过需要指定envir才能使函数工作的情况。

最简单的可重现示例:

g1 <- function(x) {
  args <- as.list(match.call())
  args[[1]] <- NULL # remove the function call
  do.call(print, args, quote = FALSE) # call print()
}

g2 <- function(x) {
  args <- as.list(match.call())
  args[[1]] <- NULL # remove the function call
  do.call(print, args, quote = FALSE, envir = parent.frame()) # call print(), specifying envir
}

h1 <- function(x, y) {
  g1(x*y)
}

h2 <- function(x, y) {
  g2(x*y)
}
Run Code Online (Sandbox Code Playgroud)

使用这些函数,h2()行为就像人们想象的那样,但h1()不会:

h1(2, 3)
#Error in print(x) : object 'y' not found

h2(2, 3)
#[1] 6

y <- 100
h1(2, 3)
#[1] 600 
## Looks like g1() took the value of y from the global environment

h2(2, 3)
#[1] 6
Run Code Online (Sandbox Code Playgroud)

有人可以向我解释这里发生了什么吗?

注:有一个相关的帖子在这里,但我的阅读答案不具体说明什么do.call()用呢envir变量。

G. *_*eck 5

?do.call 说:

环境
评估呼叫的环境。如果 what 是字符串并且参数是符号或带引号的表达式,这将是最有用的。

如果 的what=参数do.call是一个字符串,我们可以很容易地说明这一点。然后envir=确定它在哪里查找。

e <- new.env()
e$f <- function() 2
f <- function() 3
do.call("f", list())
## [1] 3
do.call("f", list(), envir = e)
## [1] 2
Run Code Online (Sandbox Code Playgroud)

问题中的代码显示的参数也是如此。请注意,参数已被引用,因为match.call()正在使用。

是什么的情况下发生的h1,并g1是,这是有效的内部运行g1

do.call(print, list(call("*", quote(x), quote(y))), quote = FALSE)
Run Code Online (Sandbox Code Playgroud)

现在它找到xin g1(因为g1有一个参数x)但没有ying1所以它查找父环境,g1它的父环境是它找到的全局环境y

在 和 的情况下h2g2它在g2以下位置运行:

do.call(print, list(call("*", quote(x), quote(y))), quote = FALSE, envir = parent.frame())
Run Code Online (Sandbox Code Playgroud)

和它发现xyh2其的parentframe g2

注意父环境和父框架不一样:

  • 父环境由定义函数的位置决定,因此如果函数是在全局环境中定义的,那么其父环境就是全局环境。
  • 父框架是调用者的环境