Menu
Coddy logo textTech

Domknięcia ze stanem

Część sekcji Logika i przepływ sterowania ścieżki R w Coddy. Lekcja 30 z 64.

Wewnątrz funkcji operator <- tworzy zmienną lokalną. Operator <<- przypisuje wartość do zmiennej o tej samej nazwie w funkcji zewnętrznej, dzięki czemu domknięcie może aktualizować przechwyconą wartość:

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

Wynik:

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

Każdy licznik utworzony przez funkcję tworzącą ma własne count, więc liczniki nigdy na siebie nie wpływają:

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

Wynik:

[1] 3
[1] 1

Przy zwykłym <- wewnątrz domknięcia aktualizacja tworzy nową zmienną lokalną, która znika po każdym wywołaniu, a przechowywana wartość nigdy się nie zmienia:

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

Wynik:

[1] 1

Funkcja tworząca może zwrócić listę domknięć, które współdzielą te same zmienne. Razem zachowują się jak mały obiekt z własnymi danymi:

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

Wynik:

[1] 15
challenge icon

Wyzwanie

Łatwy

Uzupełnij make_counter(). Zwraca funkcję, która za każdym razem, gdy zostanie wywołana, zwiększa swój licznik o 1 i zwraca nową wartość, zaczynając od 1.

Dostarczony kod tworzy dwa liczniki: a i b. Odczytuje rozdzieloną przecinkami listę a i b, wywołuje pasujący licznik dla każdego elementu i wypisuje każdą zwróconą wartość w osobnym wierszu.

Spróbuj swoich sił

make_counter <- function() {
  # Wpisz tutaj swój kod
  function() 0
}

# Dostarczony kod wejścia/wyjścia: pozostaw go bez zmian
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 iconSprawdź się

Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.

Wszystkie lekcje w sekcji Logika i przepływ sterowania

Poćwicz samodzielnie: Kompilator R online