A factory returns a function that closes over bindings from the factory's frame. Those free variables stay live in the returned function's enclosing environment — lexical capture, not a copy of values at call time for mutable cells.
R Expert · Lesson 1 · On the house
Closures and factories
Factory functions, lexical capture, private env state. Lesson 1 is free — on the house.
Lessons · R Expert · Lesson 1 of 10 · On the house
Closures and factories
Factory functions, lexical capture, private env state.

Prefer a private e <- new.env(parent = emptyenv()) (or a list of cells updated via <<- only inside the factory) over top-level <<-. The still uses assign/get on a sealed env so state is private and does not pollute .GlobalEnv.
environment(f) of the returned closure is the factory frame (or the private env you attached). Two factories yield independent counters: each closure owns its own captured cell.
local({ ... }) can also mint a closure with a fresh frame. Expert rule: return functions that close over state; avoid <<- walking into .GlobalEnv for library code.
Misses: assuming each call to the factory shares one global counter, using Python nonlocal keywords, or mutating a captured numeric with n <- n + 1 without <<-/assign (that creates a local n and leaves the outer cell unchanged).
closures-factories
make_counter <- function(start = 0L) {
e <- new.env(parent = emptyenv())
assign("n", as.integer(start), envir = e)
function(step = 1L) {
assign("n", get("n", envir = e) + as.integer(step), envir = e)
get("n", envir = e)
}
}
a <- make_counter(0L)
b <- make_counter(10L)
print(c(a(), a(2L), b(), environment(a) != environment(b)))Quiz
What does a factory return here?
Quiz
Why use new.env(parent = emptyenv()) for the cell?
Quiz
How do a and b stay independent?
Quiz
What goes wrong with n <- n + 1 inside the closure without <<- or assign?
Check
Match the still for: Closures and factories.
Open-book: the answers are on this page. Pass every quiz and check (5) to mark the lesson done. This visit: 0/5.