do.call
州的文件:
如果
quote
是FALSE
(默认值),则会评估参数(在调用环境中,而不是envir
)。
这句话会告诉我,在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)
}
使用这些功能,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
有人可以向我解释这里发生了什么吗?
注意:有一篇相关的帖子here,但在我看来,答案没有明确说明do.call()
对envir
变量的作用。
答案 0 :(得分:4)
?do.call
说:
ENVIR
评估呼叫的环境。这将会 如果什么是字符串和参数是最有用的 符号或引用的表达。
如果what=
的{{1}}参数是一个字符串,我们可以很容易地说明这一点。然后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
以来,参数已被引用。
match.call()
和h1
的情况是,g1
g1
现在它在do.call(print, list(call("*", quote(x), quote(y))), quote = FALSE)
中找到x
(因为g1
有一个参数g1
),但x
中没有y
所以它查看g1
的父环境,它是找到g1
的全局环境。
如果是y
和h2
,则会在g2
中执行此操作:
g2
并在do.call(print, list(call("*", quote(x), quote(y))), quote = FALSE, envir = parent.frame())
中找到x
和y
,这是h2
的父框架。
请注意,父环境与父框架不同: