在这里,我创建了一个未评估的表达式:
e2 <- expression(x+10)
Run Code Online (Sandbox Code Playgroud)
如果我提供的环境x定义如下
env <- as.environment(list(x=20))
eval(e2,env)
Run Code Online (Sandbox Code Playgroud)
R将报告错误:
Error in eval(expr, envir, enclos) : could not find function "+"
Run Code Online (Sandbox Code Playgroud)
这是可以理解的,因为它是env从头开始创建的环境,也就是说,它没有+定义的父环境.
但是,如果我+在列表中提供要转换为这样的环境
env <- as.environment(list(x=20,`+`=function(a,b) {a+b}))
eval(e2,env)
Run Code Online (Sandbox Code Playgroud)
评估工作正常,产生30.
但是,当我+在列表中定义时,它是一个二进制函数,它的主体也使用+中定义的{base}.我知道函数返回在R中被懒惰地评估,但为什么这可以工作?如果a+b在函数体中进行了懒惰的评估,当我eval在e2内部调用时env,即使+在没有父环境的环境中定义,它仍然应该+自己调用,这应该以无限循环结束.为什么不这样发生?这里的机制是什么?
当您在此处定义环境时:
\n\nenv <- as.environment(list(x=20,`+`=function(a,b) {a+b}))\nRun Code Online (Sandbox Code Playgroud)\n\n那么函数定义实际上是在.GlobalEnv( 即执行定义的地方定义的。您可以验证这一点:
$ environment(env$`+`)\n<environment: R_GlobalEnv>\nRun Code Online (Sandbox Code Playgroud)\n\n这个观察值得思考一下:一个函数可以是环境的成员x,但又属于y(其中\xe2\x80\x9c属于\xe2\x80\x9d意味着它的对象查找使用y而不是x)。
并且.GlobalEnv了解+,因为它是在其父级中的某个位置定义的(可通过 访问search())。
顺便说一句,如果您使用list2env而不是as.environment,您的初始代码将会起作用:
$ env = list2env(list(x = 20))\n$ eval(e2, env)\n30\nRun Code Online (Sandbox Code Playgroud)\n\n原因是,与 不同as.environment,list2env默认情况下使用当前环境作为新环境\xe2\x80\x99s 父环境(这可以通过参数控制parent)。as.environment相比之下,使用空环境(当从列表创建环境时)。
| 归档时间: |
|
| 查看次数: |
61 次 |
| 最近记录: |