0

在以下示例中,我尝试使用env_get. 第一位按预期工作。

library(rlang)
e1 <- env(a = 'a')

# works as expected
f <- function() {
  env_get(
    env = caller_env(), 
    nm = 'a', 
    inherit = TRUE, 
    default = 'not found')
}
exec(f, .env = e1)
#> [1] "a"

# two levels deep of function calls doesn't work even though inherit = TRUE
g <- function() f()
exec(g, .env=e1)
#> [1] "not found"


# modifying the depth of caller_env in f does work
f <- function() {
  env_get(
    env = caller_env(2), # <------ changing this
    nm = 'a', 
    inherit = TRUE, 
    default = 'not found')
}
exec(g, .env=e1)
#> [1] "a"

reprex 包于 2021-12-28 创建(v2.0.1)

我希望第二位,调用execwithg.env=e1起作用,因为调用env_gethas inherit=TRUE。我的理解是它会在 中caller_env查找,什么也没有,然后在其父项中查找"a",但这不起作用。进一步让我感到困惑的是,当我明确指示env_get向上查找 2 个级别时,这确实有效。

我对这种继承应该如何工作有误解吗?

4

1 回答 1

0

您对两个概念感到困惑:

  • 调用环境:函数被调用的地方。这是 的返回值caller_env()
  • 执行/评估环境:评估对象/功能的地方。这是 的返回值current_env()

当您exec在环境中使用函数时e1,该函数将在 中被调用e1,但其参数和编写在其主体中的过程将在隔离环境中进行评估,即current_env(). 通常,current_env()只是暂时存在,在功能评估完成后会被销毁。另一个重要的事情是,父环境current_env()不是caller_env()创建函数的位置。例如,

e1 <- new.env()
h <- function() {
  print(c(
    h_evaluated_in = current_env(), 
    h_called_in = caller_env(), 
    parent_of_current = parent.env(current_env())
  ))
}
list(e1_is = e1); exec(h, .env = e1); exec(h, .env = e1)

输出(注意h每次在不同的环境中评估)

$e1_is
<environment: 0x000002e731f5c1b8>

$h_evaluated_in
<environment: 0x000002e731f59cb0>

$h_called_in
<environment: 0x000002e731f5c1b8>

$parent_of_current
<environment: R_GlobalEnv>

$h_evaluated_in
<environment: 0x000002e731f58180>

$h_called_in
<environment: 0x000002e731f5c1b8>

$parent_of_current
<environment: R_GlobalEnv>

现在我们可以回到你的例子。

  • 在第一种情况下,f被调用e1f在一些孤立的环境中执行(称为temp)。在temp中,f调用env_get(...). 的caller_env()就是f这样e1e1的父环境是global_env(). env_get(...)停下来,e1因为它在a那里找到了一个绑定。

  • 在第二种情况下,g调用 in e1g在一些孤立的环境中执行(称为temp)。在temp中,g调用f(). caller_env()of因此ftemptemp的父环境是global_env(). 在temp或中env_get(...)找不到绑定,因此 return 。aglobal_env()"not found"

  • 在最后一种情况下,g在 中调用e1g在一些孤立的环境中执行(称为temp)。在temp中,g调用f(). caller_env()of因此ftempcaller_env(2)offe1因为g调用f()和被g调用e1e1的父环境是global_env(). env_get(...)停下来,e1因为它在a那里找到了一个绑定。

进一步阅读

环境 - 高级 R

于 2021-12-29T13:46:20.177 回答