クロージャとは何ですか?
クロージャは、クロージャが呼び出される環境にバインドされた変数を持つ関数コードのブロックです。
閉包にはいくつかの重要な特性があります:
- それはオブジェクトのように渡すことができます(しかし、それは必ずしもそれがオブジェクトであることを意味するわけではありません。)、
- クロージャは一つのスコープで定義され、完全に異なるスコープで呼び出すことができます。
- 作成時にそのスコープ内の変数を記憶しています; つまり、クロージャは、定義された時点でその字句環境の知識を保持します。
ブロック
ブロックはRubyのクロージャの単純な形式です。 基本的にRubyの他のすべてとは異なり、ブロックはオブジェクトではありません。
ブロックはdo...end
または{}
で構成されます。
イテレータと列挙子の操作からのブロックに精通している必要があります。
ここでは、ブロックの二つのよく知られた例があります:
.each
列挙子メソッドは、ブロックを引数として受け取り、コレクション内の各要素に対して指定されたブロックを一度呼び出します。
array.each do |x| puts xend#orarray.each { |x| puts x }
RSpecテスト内でこれを見たことがあるかもしれません。before(:each)
メソッドには、同じコンテキスト内の各テストに対して生成されるブロックが与えられます。
before(:each) do @language = "Ruby"end
Procs
ProcsはRubyのクロージャの一種であり、ブロックと非常によく似ていますが、いくつかの重要な違いがあります:
- procはローカル変数に代入でき、
- procインスタンスは
call
メソッドを呼び出すことによって実行され、 - 複数のprocをメソッドに渡すことができます。しかし、基本的には、procは、Procクラスのインスタンスに割り当てられてオブジェクトに変換されるブロックです。
したがって、procの作成はクラスのインスタンス化と非常によく似ています。
ここでは、ブロックをProcクラスのインスタンスに割り当て、それを変数に割り当てています。 次に、メソッド
.call
を呼び出しています:greeting = Proc.new { "Hello!" }greeting.call=> "Hello!"
Procsは、
.call
メソッドに渡される引数を受け入れることもできます:greeting = Proc.new { |name| "Hello, #{name}!" }greeting.call("Amanda")=> "Hello, Amanda!"
ラムダ
ラムダは、機能的にprocとそれほど違いはありません。
ここでは、それぞれ列挙子に渡されるラムダです。 それをブロックに変換する前の
&
は、それぞれが引数として期待しています。plus_one = lambda { |n| puts n + 1 }array = array.each(&plus_one)=> 2=> 3=> 4
ラムダもこの面白い方法で宣言することができます:
plus_one = ->(n) { puts n + 1 }
Lambdasとprocsはほぼ同じ意味で使用されますが、2つの間にはいくつかの違いがあります:
- lambdasは一定量の引数を期待し、それらをチェックします。procsは欠落している引数に対して
nil
を返しますが、エラーをスローしません - 彼らは別の方法で返思考を閉じる
これがあなた、特にprocsとlambdasを混乱させている場合は、心配しないでください! Procsとlambdasは素晴らしいですし、興味深い、強力なコードを書くことができます。 しかし、一日一日、あなたは彼らと全体の多くを作業することはありません。 ブロックは、しかし、あなたは毎日と対話します。 それらを最もよく知ることに焦点を合わせなさい。
- lambdasは一定量の引数を期待し、それらをチェックします。procsは欠落している引数に対して