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] 3Cada 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] 1Com 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] 1Uma 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] 15Desafio
FácilComplete 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 = "")
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
1Strings em Profundidade
Substrings com substr()Formatação com sprintf()Dividindo e UnindoPesquisando StringsSubstituindo TextoRecapitulação - Criador de Nome de Usuário4Matrizes
Criando MatrizesIndexando MatrizesResumos de Linhas e ColunasAritmética de MatrizesRecapitulação - Tabela de Assentos10Fluxo de Controle Avançado
A Função switch()ifelse() Vetorizadorepeat e breakFunções RecursivasRevisão — Classificador de Notas2Consultas de Chave-Valor
Consultas em Vetores NomeadosVerificando ChavesAdicionando e Removendo ChavesPercorrendo NomesRecapitulação - Mesa de Ações5Projeto - Boletim de Notas
Adicionando AlunosRegistrando Notas3Conjuntos e Contagem
Valores ÚnicosOperações com ConjuntosTestes de PertinênciaContagem com table()Recapitulação - Convidados do Evento6Funções como Valores
Funções AnônimasPassando FunçõesRetornando FunçõesClosures com EstadoRecapitulação - Regras de Desconto9Data Frames
Criando Data FramesColunas e LinhasFiltrando LinhasAdicionando e OrdenandoRecapitulação - Relatório de Vendas12Projeto - Rastreador de Despesas
Registro de DespesasGastos TotaisPratique por conta própria: Compilador de R online