Ruby
 Computer >> コンピューター >  >> プログラミング >> Ruby

ブロック、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が実行されます。

この投稿を楽しんでいただけたでしょうか。

以下のフォームで登録して、これを友達と共有することを忘れないでください 🙂


  1. PCでWhatsAppWebを使用する方法:究極のガイド

    WhatsApp Webは、コンピューター上のWhatsAppメッセージをすばやく簡単に読んで返信する方法を提供します。それはあなたがあなたのブラウザからオンラインでWhatsAppを使うことを可能にします。このガイドでは、PCでWhatsAppWebを使用する方法を示します。 WhatsAppWebを実行するために必要なもの 大まかに言えば、それは簡単なプロセスであり、必要なアイテムが手元にあります。しかし、徹底するために、ここにリストがあります。 リアカメラが機能しているAndroidフォンまたはiPhone。 GoogleChromeなどの最新のWebブラウザを搭載したラップトップ

  2. Mac上のAndroidメッセージの究極のガイド

    Mac 上の Android メッセージ ?不可能に聞こえますよね? 2 つのブランド間の競争が激しいため、ほとんどの人は Android と Mac は連携しないと考えています。ただし、Google は会話をユーザーにとって便利で柔軟なものにしたいと考えているため、Android Messages を開発しました。 このメッセージング プラットフォームは、PC デバイスと Mac デバイスの両方で使用できます。したがって、Mac コンピューターをお持ちの場合は、使用するのが難しくないので心配する必要はありません。 Android メッセージは複数のデバイスで互換性があるため、さまざま