web-dev-qa-db-ja.com

ダブル*(スプラット)演算子は何をしますか

このように宣言された関数を見ましたか?

def foo a, **b
  ...
end

単一の*が感嘆符演算子であることを理解しています。 **はどういう意味ですか?

196
Roy Lee

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}]
345
Dogbert

これは、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の場合、コードはかなり簡潔になります。

40
Daniel Rikowski

さらに、呼び出し側で次のように使用できます。

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}
13
kuboon