默认参数中的奇怪行为包括eval函数的parent.frame()

时间:2015-04-04 02:42:01

标签: r expression-evaluation

我目前在理解eval函数的行为方面遇到了一些问题 - 特别是在没有提供参数的情况下的enclos / third参数/使用默认参数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)因此,parent.frame()在eval的本地环境中进行评估。 Hadley在When/how/where is parent.frame in a default argument interpreted?

中证实了这一点

3)因此,最后一个表达式应该解析为eval(a + z,list(a = 7),执行名称的环境)

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

有人可以解释这个逻辑有什么问题吗?

1 个答案:

答案 0 :(得分:1)

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

简单地说,

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

name(z)

# [1] 5

因此,在a之前,eval(t, list(a=7))仍然未知,z已经可用。如果未在z中定义name,则会在.GlobalEnv中查找(a+z)。可能违反直觉的是a未定义,除非您为z指定了一个环境。但是对于{{1}},没有必要这样做。