by Karl-Kuno Kunze
This post gives you an idea of what a closure is. I first motivate why it is helpful to know about the concept. Then I introduce the notion of an environment. Having this we build a closure.
Sometimes you may run into error messages like: object of type ‘closure’ is not subsettable. To understand what R wants to tell you here, the notion of a closure is of quite some help. To put it briefly: A closure is a function together with an environment.
Firstly, we look at environments and then we connect an environment with a function. That is all it needs to build a closure.
Environment
An environment is a container that holds a set of objects. As everything is an object in R, an environment is an object, too. We first create two environments and then play around with them a little:
1 2 3 4 5 6 |
env1 <- new.env() env2 <- new.env() env1[["iAm"]] <-"Environment 1" # One way of creating objects in an environment env2$iAm <- "Environment 2" # Another way get("iAm", envir = env1) # One way of accessing objects in an environment |
1 |
## [1] "Environment 1" |
1 2 |
env2$iAm # Another way of accessing objects in an environment |
1 |
## [1] "Environment 2" |
There are several functions to access and manipulate objects in environments. Check with(), within() and attach() to name some.
Every environment resides in a parenting environment. This is the same as saying it is an object that is defined in the parenting environment.
1 2 |
parent.env(env1) |
1 |
## <environment: R_GlobalEnv> |
Closure
Now we define a function that prints the contents of object iAm. This implicitly connects the global environment to the function to make a closure.
1 2 3 4 |
iAm <- "R_GlobalEnv" envFun <- function() cat("I belong to :", iAm) envFun() |
1 |
## I belong to : R_GlobalEnv |
Now we connect environment env1 with the function to make another closure:
1 2 3 |
environment(envFun) <- env1 envFun() |
1 |
## I belong to : Environment 1 |
Now we connect environment env2 with the function to make still another closure:
1 2 3 |
environment(envFun) <- env2 envFun() |
1 |
## I belong to : Environment 2 |
Re-attaching the Global Environment works like this:
1 2 3 |
environment(envFun) <- .GlobalEnv envFun() |
1 |
## I belong to : R_GlobalEnv |
If you start R from scratch and define a function, it will form a closure with the Global Environment, i.e. have the Global environment attached.
Now, if you want to provoke the error message above, this is a way to do it:
1 2 |
envFun[] |
1 |
## Error in envFun[]: Object of type 'closure' is not subsettable |
You cannot build subsets of functions, which comes quite natural – and is no surprise.
Pingback: First Aid for Closures | R Institute Blog