Ruby、Proc、およびlambdaのダークサイド

多くの人は、その美しさと柔軟性のためにカットを愛しています。 しかし、Ruby言語のダークサイドを知らない人もいます。 今日は、多くの人がそれを使用していますが、その秘密を知っている人は多くありません。 したがって、その日のテーマはブロックです!



ルビーのブロックはほぼどこでも使用され、多くの場合、メソッドを置き換えます。 しかし、メソッドとブロックの間には大きな違いがあります。



最初の違い:

ブロックには、ブロックのスコープで宣言された変数が表示されますが、メソッドは表示されません。



ブロックを使用した例:

hello = "Hello World"

l = lambda {puts hello}

l.call #=> Hello World => nil







メソッドを使用した例:

def say_hello

puts hello

end

hello = "Hello World"

say_hello #=> NameError: undefined local variable or method `hello'







ご覧のとおり、メソッドは変数を引数として渡すまで変数を参照しません



2番目の違い:

受け入れられた引数に対するメソッドとブロックの感度。 メソッドは引数に非常に敏感であり、メソッドに記述されている引数の数だけを渡すことができます。 そうしないと、結果の代わりにエラーが発生します。

ブロックを使用すると、問題はより単純で複雑になります。Rubには、Proc.new {}とlambda {}の2つのタイプのブロックがあり、それぞれが引数に対して異なる反応を示します。



p = Proc.new { |i, k| [i, k] }

l = lambda { |i, k| [i, k] }



p.call("hello", "world") # => ["hello","world"]

p.call("hello") # => ["hello, nil]

p.call # => [nil, nil]

p.call("hello", "world", "bye") # => ["hello", "world"]



l.call("hello", "world") # => ["hello", "world"]

l.call("hello") # ArgumentError: wrong number of arguments (1 for 2)

l.call # ArgumentError: wrong number of arguments (0 for 2)

l.call("hello", "world", "bye") # ArgumentError: wrong number of arguments (3 for 2)








Vordebaにとっては、このような違いが少し面倒ではありますが(まったく同じブロックのように思えますが)、すべてが明確になっていますが、慣れることはできますが、これらは単なる花です! :)

前の例では、2つ以上の引数を持つことができるブロックを調べました。 論理的には、引数が1つでも引数がない場合でも、何も変更しないでください。 しかし、人生は複雑で不誠実なものなので、ルビーには独自の論理観があります。



p = Proc.new { |i| i }

l = lambda { |i| i }



p.call("hello") # => "hello"

p.call("hello", "world") # => ["hello", "world"] # warning: multiple values for a block parameter (2 for 1)

p.call # => nil # warning: multiple values for a block parameter (0 for 1)



l.call("hello") # => "hello"

l.call("hello", "world") # => ["hello", "world"] # warning: multiple values for a block parameter (2 for 1)

l.call # => nil # warning: multiple values for a block parameter (0 for 1)








この異常なイベントの変わり目はどうですか? 前の例から、新参者は2つの異なるブロックがあり、両方が引数に対して異なる反応をすることに気付きましたが、この例の後、すべてが逆さまになったため、新参者はエラーではなく警告を受け取りました。 言語のこの部分を学習し始めたばかりの人では、脳が起動してフリーズします。 しかし、ここのマッツは私たちの脳がリラックスすることを許可しません。 どうぞ



p = Proc.new { puts " " }

l = lambda { puts " " }



p.call # => nil

p.call("hello") # => nil



l.call # => nil

l.call("hello") # => nil








すべてのパターンとロジックのルールのギャップの最後の仕上げ。 NLPトレーニングは、パターンを破って個人の潜在意識にアクセスする方法を教えます。これはそのような例の1つです。 引数がない場合、両方のタイプのブロックは同じように反応します。



少し要約できます。 ルビーには、引数を使用した2種類の作業があります-厳密と不定(厳密&緩い)です。 メソッドは常に強い引数の原理で動作し、Procブロックは未定義の引数の原理で動作しますが、ラムダブロックは、2つ以上の引数がある場合はストリクトモードで動作し、引数がないか単一の引数がある場合は不定モードで動作します。



lambdaブロックとProcブロックには別の違いがあります。 この違いは見返りにあります。

ラムダブロックは、ブロックから結果を返すだけです。例:



def max_element

l = lambda { return [1,2,3,4] }

array = l.call

return array.max

end

max_element # => 4








また、Procはブロックから結果を返す代わりに、動作が少し異なります。Procは、宣言されたゾーンで結果を返します。次に例を示します。



def max_element

p = Proc.new { return [1,2,3,4] }

array = p.call

return array.max # Proc

end

max_element # => [1,2,3,4]








ご覧のとおり、return array.maxはそこに到達しませんでした。その前にpブロックがreturnを呼び出したためです。

Rubyは素晴らしい創造性の機会を提供する素晴らしい言語ですが、知っておくべき暗い側面があります:)



All Articles