<<-
é mais útil em conjunto com fechamentos para manter o estado. Aqui está uma seção de um artigo recente:
Um fechamento é uma função escrita por outra função. Os fechamentos são assim chamados porque incluem o ambiente da função pai e podem acessar todas as variáveis e parâmetros nessa função. Isso é útil porque nos permite ter dois níveis de parâmetros. Um nível de parâmetros (o pai) controla como a função funciona. O outro nível (a criança) faz o trabalho. O exemplo a seguir mostra como usar essa ideia para gerar uma família de funções de poder. A função pai ( power
) cria funções filho ( square
e cube
) que realmente fazem o trabalho duro.
power <- function(exponent) {
function(x) x ^ exponent
}
square <- power(2)
square(2) # -> [1] 4
square(4) # -> [1] 16
cube <- power(3)
cube(2) # -> [1] 8
cube(4) # -> [1] 64
A capacidade de gerenciar variáveis em dois níveis também possibilita manter o estado através de invocações de funções, permitindo que uma função modifique variáveis no ambiente de seu pai. A chave para gerenciar variáveis em diferentes níveis é o operador de atribuição de seta dupla <<-
. Diferente da atribuição usual de seta única ( <-
) que sempre funciona no nível atual, o operador de seta dupla pode modificar variáveis nos níveis pai.
Isso torna possível manter um contador que registra quantas vezes uma função foi chamada, como mostra o exemplo a seguir. Cada vez que new_counter
é executado, ele cria um ambiente, inicializa o contador i
nesse ambiente e cria uma nova função.
new_counter <- function() {
i <- 0
function() {
# do something useful, then ...
i <<- i + 1
i
}
}
A nova função é um fechamento e seu ambiente é o ambiente envolvente. Quando os fechamentos counter_one
e counter_two
são executados, cada um modifica o contador em seu ambiente fechado e, em seguida, retorna a contagem atual.
counter_one <- new_counter()
counter_two <- new_counter()
counter_one() # -> [1] 1
counter_one() # -> [1] 2
counter_two() # -> [1] 1