Menu
Coddy logo textTech

Closures com Estado

Parte da seção Lógica e Fluxo do Journey de R da Coddy. Lição 30 de 64.

Dentro de uma função, <- cria uma variável local. O operador <<- atribui à variável com o mesmo nome na função abrangente, em vez disso, permitindo que uma closure atualize um valor que capturou:

make_counter <- function() {
  count <- 0
  function() {
    count <<- count + 1
    count
  }
}
next_id <- make_counter()
print(next_id())
print(next_id())
print(next_id())

Saída:

[1] 1
[1] 2
[1] 3

Cada contador criado pelo criador tem seu próprio count, então eles nunca interferem:

make_counter <- function() {
  count <- 0
  function() {
    count <<- count + 1
    count
  }
}
a <- make_counter()
b <- make_counter()
for (i in 1:2) a()
print(a())
print(b())

Saída:

[1] 3
[1] 1

Com um <- simples dentro da closure, a atualização cria uma nova variável local que desaparece após cada chamada, e o valor armazenado nunca muda:

make_broken <- function() {
  count <- 0
  function() {
    count <- count + 1
    count
  }
}
f <- make_broken()
for (i in 1:2) f()
print(f())

Saída:

[1] 1

Uma função criadora pode retornar uma lista de closures que compartilham as mesmas variáveis. Juntas, elas se comportam como um pequeno objeto com seus próprios dados:

make_wallet <- function(balance) {
  list(
    add = function(x) balance <<- balance + x,
    get = function() balance
  )
}
w <- make_wallet(10)
w$add(5)
print(w$get())

Saída:

[1] 15
challenge icon

Desafio

Fácil

Complete make_counter(). Ela retorna uma função que, toda vez que é chamada, adiciona 1 à sua própria contagem e retorna a nova contagem, começando em 1.

O código fornecido cria dois contadores, a e b. Ele lê uma lista separada por vírgulas de a e b, chama o contador correspondente para cada entrada e imprime cada valor retornado em sua própria linha.

Experimente você mesmo

make_counter <- function() {
  # Escreva seu código aqui
  function() 0
}

# Código de entrada/saída fornecido: mantenha-o como está
input <- suppressWarnings(readLines(file("stdin")))
counters <- list(a = make_counter(), b = make_counter())
for (k in strsplit(input[1], ",")[[1]]) cat(counters[[k]](), "\n", sep = "")
quiz iconTeste seus conhecimentos

Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.

Todas as lições de Lógica e Fluxo

Pratique por conta própria: Compilador de R online