How do you use "<<-" (scoping assignment) in R? How do you use "<<-" (scoping assignment) in R? r r

How do you use "<<-" (scoping assignment) in R?


<<- is most useful in conjunction with closures to maintain state. Here's a section from a recent paper of mine:

A closure is a function written by another function. Closures areso-called because they enclose the environment of the parentfunction, and can access all variables and parameters in thatfunction. This is useful because it allows us to have two levels ofparameters. One level of parameters (the parent) controls how thefunction works. The other level (the child) does the work. Thefollowing example shows how can use this idea to generate a family ofpower functions. The parent function (power) creates child functions(square and cube) that actually do the hard work.

power <- function(exponent) {  function(x) x ^ exponent}square <- power(2)square(2) # -> [1] 4square(4) # -> [1] 16cube <- power(3)cube(2) # -> [1] 8cube(4) # -> [1] 64

The ability to manage variables at two levels also makes it possible to maintain the state across function invocations by allowing a function to modify variables in the environment of its parent. The key to managing variables at different levels is the double arrow assignment operator <<-. Unlike the usual single arrow assignment (<-) that always works on the current level, the double arrow operator can modify variables in parent levels.

This makes it possible to maintain a counter that records how many times a function has been called, as the following example shows. Each time new_counter is run, it creates an environment, initialises the counter i in this environment, and then creates a new function.

new_counter <- function() {  i <- 0  function() {    # do something useful, then ...    i <<- i + 1    i  }}

The new function is a closure, and its environment is the enclosing environment. When the closures counter_one and counter_two are run, each one modifies the counter in its enclosing environment and then returns the current count.

counter_one <- new_counter()counter_two <- new_counter()counter_one() # -> [1] 1counter_one() # -> [1] 2counter_two() # -> [1] 1


It helps to think of <<- as equivalent to assign (if you set the inherits parameter in that function to TRUE). The benefit of assign is that it allows you to specify more parameters (e.g. the environment), so I prefer to use assign over <<- in most cases.

Using <<- and assign(x, value, inherits=TRUE) means that "enclosing environments of the supplied environment are searched until the variable 'x' is encountered." In other words, it will keep going through the environments in order until it finds a variable with that name, and it will assign it to that. This can be within the scope of a function, or in the global environment.

In order to understand what these functions do, you need to also understand R environments (e.g. using search).

I regularly use these functions when I'm running a large simulation and I want to save intermediate results. This allows you to create the object outside the scope of the given function or apply loop. That's very helpful, especially if you have any concern about a large loop ending unexpectedly (e.g. a database disconnection), in which case you could lose everything in the process. This would be equivalent to writing your results out to a database or file during a long running process, except that it's storing the results within the R environment instead.

My primary warning with this: be careful because you're now working with global variables, especially when using <<-. That means that you can end up with situations where a function is using an object value from the environment, when you expected it to be using one that was supplied as a parameter. This is one of the main things that functional programming tries to avoid (see side effects). I avoid this problem by assigning my values to a unique variable names (using paste with a set or unique parameters) that are never used within the function, but just used for caching and in case I need to recover later on (or do some meta-analysis on the intermediate results).


One place where I used <<- was in simple GUIs using tcl/tk. Some of the initial examples have it -- as you need to make a distinction between local and global variables for statefullness. See for example

 library(tcltk) demo(tkdensity)

which uses <<-. Otherwise I concur with Marek :) -- a Google search can help.