ブロック、Procs、Lambdasの究極のガイド
Rubyブロック、プロシージャ、ラムダ。
それらは何ですか?
どのように機能しますか?
それらは互いにどのように異なりますか?
この投稿を読むことで、それ以上のことを学ぶことができます!
コンテンツ
- 1Rubyブロックを理解する
- 2RubyYieldキーワード
- 3つの暗黙的ブロックと明示的ブロック
- 4ブロックが与えられたかどうかを確認する方法
- 5ラムダとは何ですか?
- 6つのラムダとProcs
- 7つの閉鎖
- 8バインディングクラス
- 9ビデオチュートリアル
- 10まとめ
- 10.1関連
Rubyブロックについて
Rubyブロックは、メソッドに渡すことができる小さな無名関数です。
ブロックはdo / end
で囲まれています ステートメントまたは角かっこで囲まれた{}
、および複数の引数を持つことができます。
引数名は、2つのパイプ|
の間で定義されます 文字。
each
を使用した場合 以前は、ブロックを使用しました!
ここに例があります :
# Form 1: recommended for single line blocks [1, 2, 3].each { |num| puts num } ^^^^^ ^^^^^^^^ block block arguments body
# Form 2: recommended for multi-line blocks [1, 2, 3].each do |num| puts num end
Rubyブロックを使用すると、ロジック(コード)を少し節約して後で使用できるので便利です。
これは、ファイルにデータを書き込んだり、ある要素が別の要素と等しいかどうかを比較したり、エラーメッセージを出力したりするようなものです。
ルビーイールドキーワード
yield
とは Rubyの意味ですか?
歩留まりはルビーのキーワードです 使用するとブロックが呼び出されます。
メソッドがブロックを使用する方法です!
yield
を使用する場合 キーワード、ブロック内のコードが実行されます &その仕事をします。
通常のRubyメソッドを呼び出すときと同じです。
ここに例があります :
def print_once yield end print_once { puts "Block is being run" }
これにより、print_once
に渡されたすべてのブロックが実行されます 、その結果、"Block is being run"
画面に印刷されます。
ご存知ですか…
そのyield
複数回使用できますか?
yield
を呼び出すたびに 、ブロックが実行されるため、これは同じメソッドを再度呼び出すようなものです。
例 :
def print_twice yield yield end print_twice { puts "Hello" } # "Hello" # "Hello"
そして、メソッドと同じように…
yield
には任意の数の引数を渡すことができます 。
例 :
def one_two_three yield 1 yield 2 yield 3 end one_two_three { |number| puts number * 10 } # 10, 20, 30
これらの引数は、ブロックの引数になります。
この例では、number
。
暗黙的ブロックと明示的ブロック
ブロックは「明示的」または「暗黙的」にすることができます。
明示的とは、パラメータリストで名前を付けることを意味します。
明示的なブロックを別のメソッドに渡すか、後で使用するために変数に保存することができます。
ここに例があります :
def explicit_block(&block) block.call # same as yield end explicit_block { puts "Explicit block called" }
&block
に注目してください パラメータ…
これがブロックの名前を定義する方法です!
ブロックが与えられたかどうかを確認する方法
yield
しようとした場合 ブロックがないと、no block given (yield)
が得られます エラー。
block_given?
を使用して、ブロックが渡されたかどうかを確認できます。 メソッド。
例 :
def do_something_with_block return "No block given" unless block_given? yield end
これにより、誰かがブロックなしでメソッドを呼び出した場合のエラーを防ぐことができます。
ラムダとは何ですか?
ラムダは、ブロックとそのパラメーターを特別な構文で定義する方法です。
このラムダを後で使用するために変数に保存できます。
Rubyラムダを定義するための構文 次のようになります:
say_something = -> { puts "This is a lambda" }
代替構文を使用することもできます:
lambda
->
の代わりに 。
ラムダを定義すると、その中のコードは実行されません。メソッドを定義してもメソッドが実行されないのと同じように、call
を使用する必要があります。 そのための方法。
例 :
say_something = -> { puts "This is a lambda" } say_something.call # "This is a lambda"
call
する方法は他にもあります lambda
、それらが存在することを知っておくのは良いことですが、call
に固執することをお勧めします わかりやすくするために。
リストはこちら :
my_lambda = -> { puts "Lambda called" } my_lambda.call my_lambda.() my_lambda[] my_lambda.===
ラムダも引数を取ることができます。例を次に示します:
times_two = ->(x) { x * 2 } times_two.call(10) # 20
lambda
に間違った数の引数を渡した場合 、通常のメソッドと同じように、例外が発生します。
Lambdas vs Procs
Procsは非常によく似た概念です…
違いの1つは、それらを作成する方法です。
例 :
my_proc = Proc.new { |x| puts x }
専用のLambda
はありません クラス。 lambda
単なる特別なProc
物体。 Proc
のインスタンスメソッドを見てください 、lambda?
があることに気付くでしょう メソッド。
今 :
procは、特に引数に関しては、ラムダとは異なる動作をします。
t = Proc.new { |x,y| puts "I don't care about arguments!" } t.call # "I don't care about arguments!"
procs
のもう1つの違い &lambda
return
にどのように反応するかです ステートメント。
lambda
return
通常、通常の方法のように。
しかし、proc
return
を試みます 現在のコンテキストから。
これが私の意味です :
次のコードを実行すると、proc
がどのように実行されるかに気付くでしょう。 LocalJumpError
を発生させます 例外。
その理由は、return
ができないためです トップレベルのコンテキストから。
これを試してください :
# Should work my_lambda = -> { return 1 } puts "Lambda result: #{my_lambda.call}" # Should raise exception my_proc = Proc.new { return 1 } puts "Proc result: #{my_proc.call}"
proc
の場合 メソッド内にあり、return
を呼び出しました そのメソッドから戻るのと同じです。
これは、次の例で示されています。
def call_proc puts "Before proc" my_proc = Proc.new { return 2 } my_proc.call puts "After proc" end p call_proc # Prints "Before proc" but not "After proc"
procs
の概要は次のとおりです。 およびlambdas
違います:
- ラムダは
-> {}
で定義されます およびProc.new {}
を使用したプロシージャ 。 - Procは現在のメソッドから戻り、ラムダはラムダ自体から戻ります。
- Procは引数の正しい数を気にしませんが、ラムダは例外を発生させます。
このリストを見ると、lambdas
procs
よりも通常のメソッドに非常に近い です。
クロージャー
Rubyプロシージャとラムダにも別の特別な属性があります。 Rubyプロシージャを作成すると、現在の実行スコープがキャプチャされます。
この概念は、クロージャと呼ばれることもあり、proc
を意味します。 定義されたコンテキストからのローカル変数やメソッドなどの値を持ち運びます。
これらは実際の値ではなく、それらへの参照を保持しているため、procの作成後に変数が変更された場合、procには常に最新バージョンが含まれます。
例を見てみましょう :
def call_proc(my_proc) count = 500 my_proc.call end count = 1 my_proc = Proc.new { puts count } p call_proc(my_proc) # What does this print?
この例では、ローカルのcount
があります 1
に設定されている変数 。
my_proc
という名前のprocもあります 、およびcall_proc
実行されるメソッド(call
を介して) メソッド)引数として渡されるprocまたはlambda。
このプログラムは何を印刷すると思いますか?
500
のように見えます これは最も論理的な結論ですが、「閉鎖」効果のため、これは1
を出力します 。
これは、プロシージャがcount
の値を使用しているために発生します procが定義された場所から、それはメソッド定義の外です。
バインディングクラス
Rubyのprocとラムダはこのスコープ情報をどこに保存しますか?
Binding
についてお話ししましょう クラス…
Binding
を作成する場合 binding
を介したオブジェクト メソッドでは、コード内のこのポイントへの「アンカー」を作成しています。
この時点で定義されたすべての変数、メソッド、およびクラスは、スコープが完全に異なる場合でも、後でこのオブジェクトを介して利用できるようになります。
例 :
def return_binding foo = 100 binding end # Foo is available thanks to the binding, # even though we are outside of the method # where it was defined. puts return_binding.class puts return_binding.eval('foo') # If you try to print foo directly you will get an error. # The reason is that foo was never defined outside of the method. puts foo
つまり、binding
のコンテキストで何かを実行します オブジェクトは、そのコードがそのbinding
と同じ場所にある場合と同じです。 定義されました(「アンカー」のメタファーを思い出してください)。
binding
を使用する必要はありません オブジェクトを直接オブジェクトしますが、これが問題であることを知っておくのは良いことです🙂
ビデオチュートリアル
まとめ
この投稿では、ブロックがどのように機能するか、Ruby procとラムダの違いを学び、ブロックを作成するたびに発生する「クロージャー」効果についても学びました。
私がカバーしなかったのはカレーの方法です。
このメソッドを使用すると、必要な引数の一部またはすべてを渡すことができます。
部分的な数の引数のみを渡すと、これらの引数がすでに「プリロード」された新しいprocが取得され、すべての引数が指定されると、procが実行されます。
この投稿を楽しんでいただけたでしょうか。
以下のフォームで登録して、これを友達と共有することを忘れないでください 🙂
-
PCでWhatsAppWebを使用する方法:究極のガイド
WhatsApp Webは、コンピューター上のWhatsAppメッセージをすばやく簡単に読んで返信する方法を提供します。それはあなたがあなたのブラウザからオンラインでWhatsAppを使うことを可能にします。このガイドでは、PCでWhatsAppWebを使用する方法を示します。 WhatsAppWebを実行するために必要なもの 大まかに言えば、それは簡単なプロセスであり、必要なアイテムが手元にあります。しかし、徹底するために、ここにリストがあります。 リアカメラが機能しているAndroidフォンまたはiPhone。 GoogleChromeなどの最新のWebブラウザを搭載したラップトップ
-
Mac上のAndroidメッセージの究極のガイド
Mac 上の Android メッセージ ?不可能に聞こえますよね? 2 つのブランド間の競争が激しいため、ほとんどの人は Android と Mac は連携しないと考えています。ただし、Google は会話をユーザーにとって便利で柔軟なものにしたいと考えているため、Android Messages を開発しました。 このメッセージング プラットフォームは、PC デバイスと Mac デバイスの両方で使用できます。したがって、Mac コンピューターをお持ちの場合は、使用するのが難しくないので心配する必要はありません。 Android メッセージは複数のデバイスで互換性があるため、さまざま