10

次のようなメソッドを定義できます。

def test(id, *ary, hash_params)
  # Do stuff here
end

しかし、これはhash_params引数を必須にします。これらも機能しません:

def t(id, *ary, hash_params=nil)  # SyntaxError: unexpected '=', expecting ')'
def t(id, *ary, hash_params={})   # SyntaxError: unexpected '=', expecting ')'

オプションにする方法はありますか?

4

5 に答える 5

13

配列拡張機能を使用することにより、ActiveSupportでこれがサポートされますextract_options!

def test(*args)
  opts = args.extract_options!
end

最後の要素がハッシュの場合は、配列からポップして返します。それ以外の場合は、空のハッシュを返します。これは、技術的には、実行したいものと同じ(*args, opts={})です。

ActiveSupport Array#extract_options!

于 2013-03-10T08:10:27.793 に答える
11

そんなことはできません。Ruby がオプションのハッシュに属するものと、オプションのハッシュに属するものをどのように判断できるかを考える *ary必要があります。Ruby はあなたの心を読むことができないので、上記の引数の組み合わせ (splat + オプション) を論理的に解決することは不可能です。

引数を再配置する必要があります。

def test(id, h, *a)

その場合h、オプションではありません。または、手動でプログラムします。

def test(id, *a)
  h = a.last.is_a?(Hash) ? a.pop : nil
  # ^^ Or whatever rule you see as appropriate to determine if h
  # should be assigned a value or not.
于 2012-12-19T21:00:02.803 に答える
4

キャスパーの回答に加えて:

スプラッシュ パラメーターを使用して、最後のパラメーターがハッシュであるかどうかを確認できます。次に、ハッシュを設定として取得します。

コード例:

def test(id, *ary )
  if ary.last.is_a?(Hash)
    hash_params =   ary.pop
  else
    hash_params =   {}
  end
  # Do stuff here

  puts "#{id}:\t#{ary.inspect}\t#{hash_params.inspect}"
end


test(1, :a, :b )
test(2, :a, :b, :p1 => 1, :p2 => 2 )
test(3, :a,  :p1 => 1, :p2 => 2 )

結果は次のとおりです。

1:  [:a, :b]    {}
2:  [:a, :b]    {:p1=>1, :p2=>2}
3:  [:a]    {:p1=>1, :p2=>2}

配列パラメーターの最後の位置にハッシュを含める必要がある場合、これは問題になります。

test(5, :a,  {:p1 => 1, :p2 => 2} )
test(6, :a,  {:p1 => 1, :p2 => 2}, {} )

結果:

5:  [:a]    {:p1=>1, :p2=>2}
6:  [:a, {:p1=>1, :p2=>2}]  {}
于 2012-12-19T21:09:42.450 に答える
2

パラメータリストの最後にあるオプションのブロックを (誤) 使用する可能性があります。

def test(id,*ary, &block)
  if block_given?
    opt_hash = block.call
    p opt_hash
  end
  p id
  p ary
end

test(1,2,3){{:a=>1,:b=>2}}
# output:
# {:a=>1, :b=>2} #Hurray!
# 1
# [2, 3]
于 2012-12-19T22:22:52.743 に答える
1

@キャスパーは正しいです。パラメータの 1 つだけが、splat 演算子を持つことができます。引数は、最初に左から右に分割されていないパラメーターに割り当てられます。残りの引数は、splat パラメータに割り当てられます。

あなたは彼が提案するようにすることができます。これを行うこともできます:

def test(id,h={},*a)
  # do something with id
  # if not h.empty? then do something with h end
  # if not a.empty? then do something with a end
end

irb 実行のサンプルを次に示します。

001 > def test (id, h={}, *a)
002?>   puts id.inspect
003?>   puts h.inspect
004?>   puts a.inspect
005?>   end
 => nil 
006 > test(1,2,3,4)
1
2
[3, 4]
 => nil 
007 > test(1,{"a"=>1,"b"=>2},3,4)
1
{"a"=>1, "b"=>2}
[3, 4]
 => nil 
008 > test(1,nil,3,4)
1
nil
[3, 4]
 => nil

おそらく、私は追加する必要があります。オプションのパラメーターを最後のパラメーターとして使用できますが、ブロック/プロシージャである必要があります。

例えば:

def test(a,*b, &c)
  puts a.inspect
  puts b.inspect
  c.call if not c.nil?
end

呼び出しの例を次に示します。

006 > test(1,2,3)
1
[2, 3]
 => nil 
007 > test(1,2,3) {puts "hello"}
1
[2, 3]
hello
 => nil 
于 2012-12-19T21:05:24.027 に答える