ブロック、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 メッセージは複数のデバイスで互換性があるため、さまざま