14

proc と lambda がアリティに対して異なる値を返すのはなぜですか?

例えば

proc   { |x = 0| }.arity       #=> 0
lambda { |a = 0| }.arity       #=> -1
proc   { |x=0, y| }.arity      #=> 1
lambda { |x=0, y| }.arity      #=> -2

参照: http://www.ruby-doc.org/core-2.0/Proc.html#method-i-arity

4

3 に答える 3

14

リンク先のドキュメントによると:

無視されない引数の数を返します。ブロックが引数を取らないと宣言されている場合は、0 を返します。ブロックが正確に n 個の引数を取ることがわかっている場合は、n を返します。ブロックにオプションの引数がある場合は、-n-1 を返します。ここで、n は必須の引数の数です。引数宣言のない proc は、|| を宣言するブロックと同じです。その引数として。

ドキュメントが言及するのを忘れているのは、プロシージャとラムダが引数をまったく同じように扱わないことです。

>> p = proc { |a = 1, b| b }
=> #<Proc:0x007ff0091ef810@(irb):1>
>> l = lambda { |a = 1, b| b }
=> #<Proc:0x007ff0098099f8@(irb):2 (lambda)>
>> p.call
=> nil
>> l.call
ArgumentError: wrong number of arguments (0 for 1..2)
    from (irb):2:in `block in irb_binding'
    from (irb):4:in `call'
    from (irb):4
    from /usr/local/bin/irb:12:in `<main>'

編集:O'ReillyのRubyプログラミング言語は、もう少し詳細な言語です。

6.5.3 プロシージャのアリティ

proc または lambda のアリティは、期待される引数の数です。(この単語は、単項、2 項、3 項などの「ary」サフィックスに由来します。) Proc オブジェクトには、期待される引数の数を返すアリティ メソッドがあります。例えば:

lambda{||}.arity # => 0. No arguments expected
lambda{|x| x}.arity # => 1. One argument expected
lambda{|x,y| x+y}.arity # => 2. Two arguments expected

Proc が * 接頭辞付きの最終引数で任意の数の引数を受け入れると、アリティの概念が混乱します。Proc がオプションの引数を許可する場合、アリティ メソッドは -n-1 の形式の負の数を返します。この形式の戻り値は、Proc が n 個の引数を必要とすることを示しますが、オプションで追加の引数を取ることもできます。-n-1 は n の 1 の補数として知られており、~ 演算子で反転できます。したがって、arity が負の数 m を返す場合、~m (または -m-1) は必要な引数の数を示します。

lambda {|*args|}.arity # => -1. ~-1 = -(-1)-1 = 0 arguments required
lambda {|first, *rest|}.arity # => -2. ~-2 = -(-2)-1 = 1 argument required

arity メソッドには、最後にもう 1 つ問題があります。Ruby 1.8 では、引数節をまったく指定せずに (つまり、|| 文字を使用せずに) 宣言された Proc は、任意の数の引数を指定して呼び出すことができます (これらの引数は無視されます)。アリティ メソッドは -1 を返し、必要な引数がないことを示します。これは Ruby 1.9 で変更されました。次のように宣言された Proc のアリティは 0 です。ラムダの場合、引数を指定して呼び出すとエラーになります。

puts lambda {}.arity # –1 in Ruby 1.8; 0 in Ruby 1.9

編集 2: Stefan は、コメントで異なる正確な理由を追加します。

http://www.ruby-doc.org/core-2.0/Proc.html#method-i-call

複数のパラメータを持つ に誤った数のパラメータが渡されると、またはエラーがprocs生成されます。またはを使用して作成された場合、余分なパラメータは黙って破棄されます。lambda->()ProcprocsProc.newKernel.proc

于 2013-06-07T14:43:34.887 に答える
2

他の 2 つの回答を読んだ後、#arity メソッドは薄い氷を踏んでいると思います。順序付けられた引数の固定数については、#arity以前は完全に OK の方法でした。次に、オプションの引数が追加されたときに、単一の整数によるアリティ表現に固執するために、マイナス記号がフラグとして利用されました。しかし、すでに引数フィールド情報は破棄されています。1ary または 2ary-> a, b=1 { a + b }は と同じアリティ (-2) を示し-> a, *b { a + b.sum }、1 から任意の数の引数を取ります。1.9で動作が変更された後#arity、別の打撃が 2.0 で発生しました。ここでは、名前付き引数が導入されましたが、#arity. 繰り返しになりますが、必須およびオプションの名前付き引数があり、さらにハッシュ スプラッシュで任意の数のそれらを収集する可能性があります**。私は期待するだろう#arity将来的に再びその動作を変更する方法...

于 2013-06-07T20:30:10.557 に答える
2

ここで述べたように:( Proc と Lambda の違い)、proc と lambda の主な違いの 1 つは、「メソッドと同様に、lambda には厳密な引数チェックがありますが、非 lambda Proc にはブロックのように緩やかな引数チェックがあります。」

したがって、アリティは必要な引数の数に基づいているため、これはプロシージャとラムダの間で異なります。

于 2013-06-07T14:44:44.087 に答える