What does it mean - in R?

8

What does the <<- operator in R mean, what are their differences from <- , and under what circumstances can it be useful?

    
asked by anonymous 22.09.2014 / 04:01

2 answers

12

I'll explain with an example.

> objeto_fora_da_funcao <- 1
> f <- function() {
    objeto_fora_da_funcao <- 10
    return(objeto_fora_da_funcao)
}

Outputs

> f()
# [1] 10

> objeto_fora_da_funcao
# [1] 1

Now, let's change <- by <<- within function f :

> objeto_fora_da_funcao <- 1
> f <- function() {
    objeto_fora_da_funcao <<- 10
    return(objeto_fora_da_funcao)
}

Notice the outputs now:

Outputs

> objeto_fora_da_funcao
# [1] 1

> f()
# [1] 10

> objeto_fora_da_funcao
# [1] 10

What is behind this is the way R saves objects in environments, which could be seen as sets of objects (numbers, vectors, data.frames, functions, etc.).

<<- is generally useful inside functions, because the functions work with their own, temporary "environments". Despite the functions of accessing global objects, the <- operator is programmed to create (or reset) objects within the environment of the respective function, only. And that's exactly why <<- exists. It will search for objects with that given name in all environments from the most specific to the most comprehensive (known as "Global environment").

This is useful when you want a function to change global variables.

    
22.09.2014 / 04:28
6
Complementing Athos' answer, here are some examples where using <<- can be useful for changing variables within the function environment without changing global variables:

Generating a counter that accumulates the value of i in the function environment (based on the workbook of Hadley):

contador <- function() {
  i <- 0
  function() {
    i <<- i + 1
    i
  }
}

cont1 <- contador()
cont1()
[1] 1
cont1()
[1] 2
cont1()
[1] 3
cont2 <- contador()
cont2() # note que o contador de cont2 é separdo de cont1
[1] 1
cont1()
[1] 4

Implementing memoization with local and <<- in fibonacci sequence (adapted example from R Inferno) :

fibonacci <- local({
  memo <- c(0, 1, rep(NA, 100))
  f <- function(x) {
    if(x == 0) return(0)
    if(x < 0) return(NA)
    if(x > length(memo))
      stop("’x’ too big for implementation")
    if(!is.na(memo[x])) return(memo[x])
    ans <- f(x-2) + f(x-1)
    memo[x] <<- ans
    ans
  }
})
fibonacci(10)
[1] 34

Generating a fibonacci sequence with replicate and <<-

fibonacci <- function(n){
  x0 <- 0
  x1 <- 1
  x <- numeric() # para assegurar que <<- não altere a variável global
  fib <- function(){x <<- x1 + x0; x0 <<- x1; x1 <<- x}
  c(x0, x1, replicate(n-2, fib()))
}

fibonacci(10)
[1]  0  1  1  2  3  5  8 13 21 34
    
22.09.2014 / 05:32