What is the mechanism that makes `+` work when defined by + in empty environment?
r
Solution
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).
Problem
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?