4

ブロックをパラメーターとして受け取るメソッドを設定しようとしています。最後のパラメーターに & プレフィックスを付けることでこれを行うことは知っていますが、渡されたら、どのように確認すればよいですか?

引数が文字列であることを確認したい場合は、is_a?(String)たとえば を使用できます。しかし、1 つのパラメーターを受け入れるブロックを受け取ったことを確認するにはどうすればよいでしょうか? それとも2?

4

2 に答える 2

11

メソッドを使用してProc#arity、ブロックが受け入れる引数の数を確認できます。

def foo(&block)
  puts block.arity
end

foo { }        # => 0
foo { |a| }    # => 1
foo { |a, b| } # => 2

ドキュメントから:

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

于 2013-11-07T15:55:02.290 に答える
4

ブロックはオブジェクトではないので、ブロックを使って何か役に立つことはできません (yieldもちろんブロックを除いて)。

つまり、それらを参照する方法はなく、名前にもバインドされていません。

def foo
  yield 'foo'
end

foo do |bar| puts bar end
# foo

内部fooでは、ブロックは変数にバインドされておらず、参照することもできないため、明らかにそのパラメーターについてもクエリできません。

ただし、Ruby にブロックを に変換してパラメーターにバインドするように依頼することはできます。Procその後、名前で参照でき以下を含む完全なProcAPI を自由に使用できますProc#parameters

def foo(&blk)
  blk.parameters
end

foo do |m1, m2, o1=:o1, o2=:o2, *splat, m3, m4, 
      ok1: :ok1, mk1:, mk2:, ok2: :ok2, **ksplat, &blk| end
# => [[:opt, :m1],
#     [:opt, :m2],
#     [:opt, :o1],
#     [:opt, :o2],
#     [:rest, :splat],
#     [:opt, :m3],
#     [:opt, :m4],
#     [:keyreq, :mk1],
#     [:keyreq, :mk2],
#     [:key, :ok1],
#     [:key, :ok2],
#     [:keyrest, :ksplat],
#     [:block, :blk]]

ただし、「ブロックのアリティ」という概念は、Ruby では複雑な概念であることに注意してください。これは、ブロックのパラメーター バインディング セマンティクスが緩いためです。ブロックのパラメータ バインディング セマンティクスは、特にアリティに関しては、メソッドのパラメータ バインディング セマンティクスとは異なります。

  • ブロックが 1 つのパラメーターのみを受け取り、複数の引数が渡された場合、それはエラーではありません。代わりに、引数はArrayパラメーターへの単一のバインドとして渡されます (パラメーターがパラメーターとして宣言されているかのように*splat)。
  • ブロックが複数のパラメーターを取り、単一の引数のみが渡される場合、その引数は に変換され、Array代わりにその個々の要素が引数として渡されます (引数として渡されたかのように*splat)。
  • ブロックが受け取るパラメーターよりも多くの引数が渡された場合、余分な引数は無視されます。
  • ブロックが受け取るパラメーターよりも少ない引数が渡された場合、余分なパラメーターは にバインドされnilます。

全体として、セマンティクスはメソッド呼び出しよりも割り当てのセマンティクスに近いです。

たとえば、 と はブロック内で必須の位置パラメータとして宣言されていますが、それらの型は 、つまりオプションのパラメータとしてリストされていることに注意m1m2Proc#parametersください:opt

つまり、1 つのパラメーターのみを宣言するブロックでも 2 つの引数を取り、2 つのパラメーターを宣言するブロックは 1 つの引数だけで呼び出すことができます。

これが役立つ 1 つの例: ミックスイン全体が、単一の要素であるEnumerableメソッドに基づいています。ただし、 の場合、実際には2 つの引数を処理する必要があります。s2 つの要素であり、2 つのパラメーターを宣言するが 1 つの引数のみを受け取るブロックは、そのパラメーター全体でその引数を「スプラット」するため、キーがバインドされ、値がバインドされずにバインドされるため、できます。すべてのs メソッドの 2 引数バージョンをコピーして貼り付けます。yieldHashkey, valueHash#each yieldArraykeyvalueEnumerable

于 2013-11-07T16:24:23.580 に答える