クロージャとスコープ
変数をキャプチャします。
「クロージャとスコープ」はCoddyKit上の無料Ruby Academyレッスンです。 これはレッスン4/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはRuby Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Ruby Academyコースには全4レッスンが含まれています。
変数の捕捉
クロージャとは、定義された場所の変数を、その場所の処理が終わった後も記憶している関数です。Procとラムダはクロージャです。
name = "Ada"
greeter = -> { puts "Hello, #{name}" }
greeter.call変数も一緒に持ち運ばれる
クロージャは値をコピーするのではなく、変数への生きた参照を保持します。そのため、後から変数を変更すると、クロージャからは新しい値が見えます。
count = 0
reader = -> { count }
count = 5
puts reader.callクロージャは変数を変更できる
参照が生きているため、クロージャは捕捉した変数を変更することもできます。
total = 0
adder = ->(n) { total += n }
adder.call(3)
adder.call(7)
puts total囲むメソッドが終了しても残る
捕捉された変数は、それを作成したメソッドが戻った後も、クロージャが存在する限り残り続けます。
def counter
n = 0
-> { n += 1 }
end
c = counter
puts c.call
puts c.call
puts c.call独立した状態
ファクトリメソッドを呼び出すたびに新しい変数が作られるため、別々のクロージャはそれぞれ独立した状態を保持します。
def counter
n = 0
-> { n += 1 }
end
a = counter
b = counter
puts a.call
puts a.call
puts b.callブロックパラメータはローカル
パイプ内で宣言したパラメータはブロック内だけで有効で、同じ名前の変数が存在していても外には漏れません。
x = 100
[1, 2, 3].each { |x| }
puts x # still 100ブロックローカル変数
パイプ内でセミコロンの後に追加の名前を記述すると、それらをブロックローカルにできます。これにより、外側の変数が誤って変更されるのを防げます。
y = "outer"
[1].each { |i; y| y = "inner" }
puts y # unchanged設定可能な関数を作る
クロージャを使うと、設定を関数に一度組み込んで、何度も再利用できます。
def power_of(exp)
->(base) { base ** exp }
end
square = power_of(2)
cube = power_of(3)
puts square.call(5)
puts cube.call(2)繰り返し処理でのクロージャ
よくある落とし穴は、ループ内で作成したクロージャがスナップショットではなく変数を捕捉することです。反復ごとにクロージャを作成すると、それぞれの値を個別に捕捉できます。
funcs = [1, 2, 3].map { |i| -> { i } }
puts funcs.map(&:call).inspectプライベートな状態のカプセル化
クロージャを使うと、関数の背後に状態を隠せます。これはオブジェクトの初期の形ともいえます。この例では、残高には返されたラムダを通してしかアクセスできません。
def make_account(start)
balance = start
deposit = ->(n) { balance += n }
show = -> { balance }
[deposit, show]
end
dep, show = make_account(100)
dep.call(50)
puts show.callまとめ
クロージャはコードを定義された場所に結び付けます。
- 周囲の変数への生きた参照を捕捉します。
- 囲んでいるメソッドが戻った後も状態が残ります。
- 各クロージャは独自の独立した変数を保持します。
def tagger(prefix)
->(text) { "[#{prefix}] #{text}" }
end
warn = tagger("WARN")
puts warn.call("low disk space")理解度チェック
クロージャについての理解度を確認しましょう。
振り返り
クロージャとスコープについて学んだことを振り返りましょう。
- Procとラムダは、周囲の変数を参照によって捕捉します。
- 捕捉された状態は、囲んでいるメソッドより長く存続します。
- 各クロージャは独立した状態を保持します。
- ブロックパラメータはローカルのままです。ブロックローカル変数には
;を使用します。
def stepper(by)
pos = 0
-> { pos += by }
end
s = stepper(5)
puts s.call
puts s.callよくある質問
「クロージャとスコープ」レッスンは無料ですか?
はい。「クロージャとスコープ」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Ruby Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Ruby Academyコースには全4レッスンが含まれています。
「クロージャとスコープ」で何を学びますか?
変数をキャプチャします。 ブラウザで直接実行するハンズオンコードでRuby Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
Ruby Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのRuby Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン4/4です。
「クロージャとスコープ」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このRuby Academyレッスンでコードを書いて実行できますか?
はい。すべてのRuby Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。