このように宣言された関数を見ましたか?
def foo a, **b
...
end
単一の*
が感嘆符演算子であることを理解しています。 **
はどういう意味ですか?
Ruby 2.0はキーワード引数を導入し、**
は*
と同じように機能しますが、キーワード引数を使用します。キーと値のペアを含むハッシュを返します。
このコードの場合:
def foo(a, *b, **c)
[a, b, c]
end
デモは次のとおりです。
> foo 10
=> [10, [], {}]
> foo 10, 20, 30
=> [10, [20, 30], {}]
> foo 10, 20, 30, d: 40, e: 50
=> [10, [20, 30], {:d=>40, :e=>50}]
> foo 10, d: 40, e: 50
=> [10, [], {:d=>40, :e=>50}]
これは、Ruby 2.0以降で使用可能なdouble splat演算子です。
すべてのキーワード引数をキャプチャします(これは単純なハッシュにすることもできます。これは、Ruby言語の一部になる前にキーワード引数をエミュレートする慣用的な方法でした)
def my_method(**options)
puts options.inspect
end
my_method(key: "value")
上記のコードは、{key:value}
をコンソールに出力します。
単一のスプラット演算子がすべての通常の引数をキャプチャするように、arrayの代わりにhash。
実際の例:
たとえば、Railsでは、cycle
メソッドは次のようになります。
def cycle(first_value, *values)
options = values.extract_options!
# ...
end
このメソッドは、cycle("red", "green", "blue", name: "colors")
のように呼び出すことができます。
これは非常に一般的なパターンです。引数のリストを受け入れ、最後の引数はオプションハッシュであり、たとえばActiveSupportのextract_options!
を使用して抽出できます。
Ruby 2.0では、これらのメソッドを簡素化できます。
def cycle(first_value, *values, **options)
# Same code as above without further changes!
end
確かにActiveSupportを既に使用している場合はわずかな改善にすぎませんが、プレーンRubyの場合、コードはかなり簡潔になります。
さらに、呼び出し側で次のように使用できます。
def foo(opts); p opts end
bar = {a:1, b:2}
foo(bar, c: 3)
=> ArgumentError: wrong number of arguments (given 2, expected 1)
foo(**bar, c: 3)
=> {:a=>1, :b=>2, :c=>3}