Menu
Coddy logo textTech

状態を持つクロージャ

CoddyのRジャーニー「ロジックとフロー」セクションの一部。レッスン 30/64。

関数内では、<- がローカル変数を作成します。演算子 <<- は代わりに、外側の関数にある同じ名前の変数に代入するため、クロージャはキャプチャした値を更新できます。

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

出力:

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

maker によって作られた各カウンターはそれぞれ独自の count を持つため、互いに干渉することはありません。

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

出力:

[1] 3
[1] 1

クロージャ内で通常の <- を使うと、更新によって呼び出しごとに消える新しいローカル変数が作成され、保存された値は決して変化しません。

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

出力:

[1] 1

メーカーは、同じ変数を共有するクロージャのリストを返すことができます。これらは一緒になると、独自のデータを持つ小さなオブジェクトのように動作します:

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

出力:

[1] 15
challenge icon

チャレンジ

簡単

make_counter()を完成させてください。これは、呼び出されるたびに自身のカウントに1を加え、新しいカウントを返す関数を返します。カウントは1から始まります。

提供されたコードは、aとbという2つのカウンターを作成します。aとbのカンマ区切りリストを読み込み、各項目に対応するカウンターを呼び出し、返された各値をそれぞれ独自の行に出力します。

自分で試してみよう

make_counter <- function() {
  # ここにコードを書いてください
  function() 0
}

# 提供された入出力コード:そのままにしておいてください
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 icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

ロジックとフローのすべてのレッスン

自分で練習してみよう: Rオンラインコンパイラ