Environments, Scoping & Closures
An environment maps names to values and has a parent.
23.1 Environments
An environment maps names to values and has a parent.
Environments have reference semantics (not copied on modify) — used for mutable state, caches, R6 objects.
e <- new.env()
assign("x", 10, envir = e); get("x", envir = e); e$y <- 5
ls(e); exists("x", envir = e); rm("x", envir = e)
environment() # current environment
globalenv(); emptyenv(); baseenv()
parent.env(globalenv())
search() # the search path: .GlobalEnv, attached packages, base
environmentName(environment(mean)) # "base"23.2 Lexical scoping
R looks up names where a function was defined, not where it's called:
Lookup order: current function environment → enclosing (defining) environments → global → packages on the search path → base → empty.
x <- "global"
f <- function() { x <- "f"; g <- function() x; g() }
f() # "f"23.3 Closures & function factories
make_counter <- function() {
count <- 0
function() {
count <<- count + 1 # modify variable in the enclosing environment
count
}
}
counter <- make_counter()
counter(); counter() # 1, 2
power <- function(exp) { force(exp); function(x) x^exp }
square <- power(2); cube <- power(3)
square(4); cube(2)23.4 Dynamic lookup & caller environments
f <- function() parent.frame() # caller's environment
sys.call(); match.call(); sys.function()
local({ tmp <- 1; tmp + 1 }) # evaluate in a temporary environment