0Pricing
Ruby Academy · レッスン

クロージャとスコープ

変数をキャプチャします。

「クロージャとスコープ」は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フィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. ブロックの復習
  2. Proc
  3. ラムダ
  4. クロージャとスコープ
← Ruby Academyに戻る