Menu
Coddy logo textTech

Fermetures avec état

Fait partie de la section Logique et flux d’exécution du Journey R de Coddy. Leçon 30 sur 64.

À l’intérieur d’une fonction, <- crée une variable locale. L’opérateur <<- affecte plutôt la variable du même nom dans la fonction englobante, ce qui permet à une fermeture de mettre à jour une valeur qu’elle a capturée :

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

Sortie :

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

Chaque compteur créé par le créateur possède son propre count, ils n’interfèrent donc jamais :

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

Sortie :

[1] 3
[1] 1

Avec un <- simple à l’intérieur de la fermeture, la mise à jour crée une nouvelle variable locale qui disparaît après chaque appel, et la valeur stockée ne change jamais :

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

Sortie :

[1] 1

Un créateur peut renvoyer une liste de fermetures qui partagent les mêmes variables. Ensemble, elles se comportent comme un petit objet avec ses propres données :

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

Sortie :

[1] 15
challenge icon

Défi

Facile

Complétez make_counter(). Cette fonction renvoie une fonction qui, chaque fois qu’elle est appelée, ajoute 1 à son propre compteur et renvoie le nouveau compteur, en commençant à 1.

Le code fourni crée deux compteurs, a et b. Il lit une liste séparée par des virgules de a et b, appelle le compteur correspondant pour chaque élément et affiche chaque valeur renvoyée sur sa propre ligne.

Essayez vous-même

make_counter <- function() {
  # Écrivez votre code ici
  function() 0
}

# Code d'entrée/sortie fourni : gardez-le tel quel
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 iconTestez-vous

Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.

Toutes les leçons de Logique et flux d’exécution

Entraînez-vous par vous-même : Compilateur R en ligne