I'm trying to understand how R's local
function is working. With it, you can open a temporary local scope, which means what happens in local
(most notably, variable definitions), stays in local
. Only the last value of the block is returned to the outside world. So:
x <- local({
a <- 2
a * 2
})
x
## [1] 4
a
## Error: object 'a' not found
local
is defined like this:
local <- function(expr, envir = new.env()){
eval.parent(substitute(eval(quote(expr), envir)))
}
As I understand it, two rounds of expression quoting and subsequent evaluation happen:
eval(quote([whatever expr input]), [whatever envir input])
is generated as an unevaluated call bysubstitute
.- The call is evaluated in
local
's caller frame (which is in our case, the Global Environment), so[whatever expr input]
is evaluated in[whatever envir input]
However, I do not understand why step 2 is nessecary. Why can't I simply define local
like this:
local2 <- function(expr, envir = new.env()){
eval(quote(expr), envir)
}
I would think it evaluates the expression expr
in an empty environment? So any variable defined in expr
should exist in envir
and therefore vanish after the end of local2
?
However, if I try this, I get:
x <- local2({
a <- 2
a * 2
})
x
## [1] 4
a
## [1] 2
So a
leaks to the Global Environment. Why is this?
EDIT: Even more mysterious: Why does it not happen for:
eval(quote({a <- 2; a*2}), new.env())
## [1] 4
a
## Error: object 'a' not found