Closures in R Programming Language

R supports anonymous functions, which can form closures. Anonymous functions are useful when you want to define a function inline without having to name it.

# This function intSeq returns another function, which
# we define anonymously in the body of intSeq. The
# returned function closes over the variable i to
# form a closure.
intSeq <- function() {
  i <- 0
  function() {
    i <<- i + 1
    i
  }
}

# We call intSeq, assigning the result (a function)
# to nextInt. This function value captures its
# own i value, which will be updated each time
# we call nextInt.
nextInt <- intSeq()

# See the effect of the closure by calling nextInt
# a few times.
print(nextInt())
print(nextInt())
print(nextInt())

# To confirm that the state is unique to that
# particular function, create and test a new one.
newInts <- intSeq()
print(newInts())

To run the program, save the code in a file (e.g., closures.R) and use the R interpreter:

$ Rscript closures.R
[1] 1
[1] 2
[1] 3
[1] 1

In R, closures work similarly to other languages. The intSeq function returns an anonymous function that increments and returns a counter. Each time we call intSeq(), it creates a new environment with its own i variable, which is then captured by the returned function.

Note that in R, we use <<- instead of = or <- to modify a variable in the parent environment from within a function. This is how we achieve the incrementing behavior in the closure.

The last feature of functions we’ll look at for now is recursion.