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] 3Chaque 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] 1Avec 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] 1Un 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] 15Défi
FacileComplé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 = "")
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
1Les chaînes en profondeur
Sous-chaînes avec substr()Mise en forme avec sprintf()Scinder et joindreRechercher dans les chaînesRemplacer du texteRécapitulatif - Créateur de nom d'utilisateur4Matrices
Créer des matricesIndexer des matricesRécapitulatifs des lignes et des colonnesArithmétique matricielleRécapitulatif - Plan de salle7La famille Apply
lapply et sapplyMap et mapplyFilter et FindReduceRécapitulatif - Pipeline de données10Structures de contrôle avancées
La fonction switch()ifelse() vectorisérepeat et breakFonctions récursivesRécapitulatif – Classificateur de notes2Recherches par clé-valeur
Recherches dans des vecteurs nommésVérifier les clésAjouter et supprimer des clésParcourir les nomsRécapitulatif - Bureau des stocks5Projet - Carnet de notes
Ajouter des élèvesEnregistrer les notes3Ensembles et comptage
Valeurs uniquesOpérations sur les ensemblesTests d’appartenanceCompter avec table()Récapitulatif - Invités à l’événement6Les fonctions comme valeurs
Fonctions anonymesPasser des fonctionsRetourner des fonctionsFermetures avec étatRécapitulatif - Règles de remise9Data Frames
Créer des Data FramesColonnes et lignesFiltrer les lignesAjouter et trierRécapitulatif - Rapport des ventes12Projet - Suivi des dépenses
Enregistrer les dépensesDépenses totalesEntraînez-vous par vous-même : Compilateur R en ligne