在空环境中由+定义时,`+`工作的机制是什么?

时间:2014-04-02 08:37:41

标签: r

在这里,我创建了一个未评估的表达式:

e2 <- expression(x+10)

如果我提供的x被定义为

的环境
env <- as.environment(list(x=20))
eval(e2,env)

R将报告错误:

Error in eval(expr, envir, enclos) : could not find function "+"

这是可以理解的,因为env是从头开始创建的环境,也就是说,它没有定义+的父环境。

但是,如果我在列表中提供+以转换为像这样的环境

env <- as.environment(list(x=20,`+`=function(a,b) {a+b}))
eval(e2,env)

评估工作正常并产生30。

但是,当我在列表中定义+时,它是一个二进制函数,它的主体也使用+ {base}中定义的。我知道函数返回在R中被懒惰地评估,但为什么这可以工作?如果函数正文中的a+b被延迟评估,那么当我在eval内为e2调用env时,即使在此环境中定义+也没有在父环境中,它仍然应该调用+本身,这应该以无限循环结束。为什么不这样发生?这里的机制是什么?

1 个答案:

答案 0 :(得分:4)

在此处定义环境时:

env <- as.environment(list(x=20,`+`=function(a,b) {a+b}))

然后函数定义实际上在.GlobalEnv中定义(即执行定义的位置。您可以验证这一点:

$ environment(env$`+`)
<environment: R_GlobalEnv>

这个观察值得思考一点:一个函数可以是环境x的成员,但属于y(其中“属于”意味着它的对象查找使用{{1}而不是y)。

x知道.GlobalEnv,因为它在父母的某处定义(可通过+访问)。

顺便提一下,如果您使用search()代替list2env,那么您的初始代码就会有效:

as.environment

原因是,与$ env = list2env(list(x = 20)) $ eval(e2, env) 30 不同,as.environment默认使用当前环境作为新环境的父级(可以通过list2env参数控制)。相比之下,parent使用空的环境(从列表创建环境时)。