【问题标题】:Strange behavior in default argument enclos =parent.frame() of eval functioneval 函数的默认参数 enclos =parent.frame() 中的奇怪行为
【发布时间】:2015-04-04 02:42:01
【问题描述】:

我目前在理解 eval 函数的行为时遇到了一些问题 - 特别是 enclos/第三个参数,当没有提供参数/使用默认参数 parent.fame() 时。

name <- function(x){
    print(substitute(x))
    t <- substitute(x)
    eval(t, list(a=7), parent.frame())
}
z <-5
name(a+z)
# returns 12, makes sense because this amounts to
# eval(a+z, list(a=7), glovalenv())


# however the return here makes no sense to me

  name2 <- function(x){
    print(substitute(x))
    t <- substitute(x)
    eval(t, list(a=7)) # third/enclosure argument is left missing
}

z <-5
name2(a+z)
# Also returns 12

我无法理解为什么第二次调用返回 12。根据我对 R 的理解,第二次调用应该会导致错误,因为

1) eval默认的第三个参数enclos= parent.frame(),没有指定。

2) 因此,在 eval 的本地环境中评估 parent.frame()。 Hadley 在When/how/where is parent.frame in a default argument interpreted?

中证实了这一点

3) 因此,最后一个表达式应该解析为 eval(a+z, list(a=7), execution environment of name)

4) 这应该返回一个错误,因为 z 没有在 name 的执行环境中定义,也没有在 list(a=7) 中定义。

有人能解释一下这个逻辑有什么问题吗?

【问题讨论】:

  • 这里name的调用环境是全局环境,但一般情况下你会错

标签: r expression-evaluation


【解决方案1】:

z 将在函数内部可用,因为它是在 .GlobalEnv 中定义的。

简单地说,

name <- function(x) {
  print(z)
}
z <- 5

name(z)

# [1] 5

所以虽然aeval(t, list(a=7)) 之前仍然未知,但z 已经可用。如果z 没有在name 中定义,它将在.GlobalEnv 中查找。可能违反直觉的是 (a+z) 是未定义的,除非您为 a 指定环境。但对于z,则无需这样做。

【讨论】:

  • 这是由于词法作用域。明白了。
  • 是的,没错,你做到了:词法作用域。 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-15
  • 1970-01-01
  • 1970-01-01
  • 2023-03-29
相关资源
最近更新 更多