Here I create an unevaluated expression:
e2 <- expression(x+10)
If I supply an environment in which x
is defined like
env <- as.environment(list(x=20))
eval(e2,env)
R will report an error:
Error in eval(expr, envir, enclos) : could not find function "+"
It is understandable since env
is an environment created from scratch, that is, it has no parent environment where +
is defined.
However, if I supply +
in the list to be converted to an environment like this
env <- as.environment(list(x=20,`+`=function(a,b) {a+b}))
eval(e2,env)
The evaluation works correctly and yields 30.
However, when I define +
in the list, it is a binary function whose body also uses + which is defined in {base}
. I know that function returns are lazily evaluated in R, but why this could work? If a+b
in the function body is lazily evaluated, when I call eval
for e2
within env
, even though +
is defined in this environment which has no parent environment, it should still calls +
in itself, which should end up in endless loop. Why is does not happen like this? What is the mechanism here?
When you define the environment here:
env <- as.environment(list(x=20,`+`=function(a,b) {a+b}))
then the function definition is actually defined in the .GlobalEnv
(namely, where the definition is executed. You can verify this:
$ environment(env$`+`)
<environment: R_GlobalEnv>
This observation is worth being pondered a little: a function can be a member of environment x
, yet belong to y
(where “belong to” means that its object lookup uses y
rather than x
).
And .GlobalEnv
knows about +
, since it is defined somewhere in its parents (accessible via search()
).
Incidentally, if you had used list2env
instead of as.environment
, your initial code would have worked:
$ env = list2env(list(x = 20))
$ eval(e2, env)
30
The reason is that, unlike as.environment
, list2env
by default uses the current environment as the new environment’s parent (this can be controlled via the parent
argument). as.environment
by contrast uses the empty environment (when creating an environment from a list).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With