do.call的envir选项如何工作?

时间:2017-12-09 23:42:14

标签: r

do.call州的文件:

  

如果quoteFALSE(默认值),则会评估参数(在调用环境中,而不是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变量的作用。

1 个答案:

答案 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的全局环境。

如果是yh2,则会在g2中执行此操作:

g2

并在do.call(print, list(call("*", quote(x), quote(y))), quote = FALSE, envir = parent.frame()) 中找到xy,这是h2的父框架。

请注意,父环境与父框架不同:

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