Rubyメソッドはブロックまたは引数のいずれかを受け入れることができますか?



Can Ruby Method Accept Either Block



解決:

確かにそれは可能です。あなたがしなければならないのは、引数が与えられているかどうかをチェックし、ブロックが与えられているかどうかもチェックすることです。

def call_me(arg = nil)は、arg.nilでない限り、「arggiven」を置きますか? block_givenの場合、「blockgiven」を配置しますか? end call_me(1)#=>引数指定call_me {'foo'}#=>ブロック指定call_me(1){'foo'}#=>引数指定#ブロック指定

または:



def call_me(arg = nil、&block)は、arg.nilでない限り、「arggiven」を置きますか? block.nilでない限り、「ブロックが与えられた」を置きますか?終わり

後者は、ブロックをProc(名前付き)に変換するので便利です。ブロック)、以下のように再利用できます。

あなたはあなた自身を実装することができますこのようなカウント方法:



module Enumerable def my_count(* args、&block)は、args.emptyの場合にサイズを返しますか? && block.nil?引数の数が間違っています(#{args.size}が指定され、1が必要です) 'args.size> 1 counter = block.nil? ? ->(i){i == args [0]}:ブロック合計end end arr = [1,2,3,4,5] p arr.my_count#=> 5 p arr.my_count(2)#=> 1 p arr.my_count(&:even?)#=> 2 p arr.my_count(2、3)#=> ArgumentError:引数の数が間違っています(2が与えられ、1が期待されます)

repl.itでそれを参照してください:https://repl.it/@jrunning/YellowishPricklyPenguin-1


はい、パラメータをオプションにし(ブロックは常にオプションです)、位置引数またはブロック引数が渡されたかどうかを確認することで、これを行うことができます。

ただし、これは少し面倒です。ほとんどのRuby実装は、実装のプライベート内部への特権アクセスを使用して問題のメソッドを実装することでこれを回避します。これにより、引数が渡されたかどうかを確認するのがはるかに簡単になります。例えば。 JRubyとIronRubyの両方にバインドする方法があります 複数のオーバーロード Java / CLIメソッドから 独身 引数の数とタイプに基づくRubyメソッド。これにより、これらの3つの「モード」を実装できます。同じメソッドの3つの単純なオーバーロードとしてカウントします。これがの例ですIronRubyから数えます。これはJRubyから数えます。



ただし、Rubyはオーバーロードをサポートしていないため、手動で実装する必要があり、少し厄介な場合があります。このようなもの:

module Enumerable def count(item =(item_not_given = true; nil))item_given =!item_not_given warn '指定されたブロックは使用されていません' if block_given? && item_given return count(&item.method(:==))if item_given return inject(0)if yield el then acc + 1 else acc end if block_given? count(&:itself)end end

ご覧のとおり、少し厄介です。単純に使ってみませんかオプションのデフォルト引数としてnilアイテムパラメータ?まあ、なぜならnilは有効な引数であり、引数を渡さない人と渡す人を区別できません。引数としてnil。

比較のために、ここに方法がありますcountはRubiniusで実装されています:

def count(item = undefined)seq = 0 if!undefined.equal?(item)each do element = Rubinius.single_block_arg seq + = 1 if item == element end elsif block_given?各seq + = 1 if yield(element)else each {seq + = 1} end seq end

オプションのパラメーターのデフォルトの引数が変数の設定などの副作用を伴う任意のRuby式であるという事実を(乱用)使用する場合、Rubiniusは特別なものを使用しますRubiniusランタイムによって提供され、同等?それ自体にのみ。