Menu
Coddy logo textTech

Closure con stato

Fa parte della sezione Logica e flusso del percorso R di Coddy. Lezione 30 di 64.

All'interno di una funzione, <- crea una variabile locale. L'operatore <<- assegna invece alla variabile con lo stesso nome nella funzione che la racchiude, così una chiusura può aggiornare un valore che ha catturato:

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

Output:

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

Ogni contatore creato dal generatore ha il proprio count, quindi non interferiscono mai:

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())

Output:

[1] 3
[1] 1

Con un semplice <- all'interno della chiusura, l'aggiornamento crea una nuova variabile locale che scompare dopo ogni chiamata, e il valore memorizzato non cambia mai:

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

Output:

[1] 1

Una funzione creatrice può restituire un elenco di chiusure che condividono le stesse variabili. Insieme si comportano come un piccolo oggetto con i propri dati:

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

Output:

[1] 15
challenge icon

Sfida

Facile

Completa make_counter(). Restituisce una funzione che, ogni volta che viene chiamata, aggiunge 1 al proprio conteggio e restituisce il nuovo conteggio, partendo da 1.

Il codice fornito crea due contatori, a e b. Legge un elenco di a e b separati da virgole, chiama il contatore corrispondente per ogni elemento e stampa ogni valore restituito su una propria riga.

Provalo tu

make_counter <- function() {
  # Escribe tu código aquí
  function() 0
}

# Código de entrada/salida proporcionado: mantenlo tal 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 iconMettiti alla prova

Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.

Tutte le lezioni di Logica e flusso

Esercitati da solo: Compilatore R online