Что делает оператор double * (splat)

Вы видели такую ​​функцию?

def foo a, **b
  ...
end

Я понимаю, что единственный * - это оператор splat. Что значит **?


person RLEE    schedule 17.08.2013    source источник


Ответы (3)


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}]
person Dogbert    schedule 17.08.2013
comment
Это прекрасно отвечает на вопрос, но у меня было небольшое дополнение. Так же, как оператор splat может использоваться для массива, который вы передаете, двойной splat может использоваться для хешей. Если opts = {d: 40, e: 50}, то foo 10, opts, f: 60 назначит {f: 60} на c, тогда как foo 10, **opts, f: 60 назначит {d: 40, e: 50, f: 60}. Чтобы достичь второго эффекта, раньше вы должны были бы явно merged массивов. - person brymck; 03.11.2013
comment
Я бы предположил, что это полезно для установки дополнительных хэш-параметров для метода - person bigpotato; 19.12.2013
comment
Вероятно, стоит отметить, что если смешивать ключевые слова-аргументы с ключевым словом splat, ключевое слово splat должно стоять после аргументов ключевого слова. - person MrMesees; 04.04.2019

Это оператор двойной знак, доступный начиная с Ruby 2.0.

Он фиксирует все аргументы ключевого слова (которые также могут быть простым хешем, что было идиоматическим способом имитации аргументов ключевого слова до того, как они стали частью языка Ruby)

def my_method(**options)
  puts options.inspect
end

my_method(key: "value")

Приведенный выше код выводит {key:value} на консоль.

Точно так же, как единственный оператор splat захватывает все обычные аргументы, но вместо массива вы получаете хэш.

Пример из жизни:

Например, в 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 код становится довольно лаконичным.

person Daniel Rikowski    schedule 17.08.2013

Кроме того, вы можете использовать его на стороне вызывающего абонента следующим образом:

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}
person kuboon    schedule 26.07.2017
comment
Вау, двойной знак аналогичен оператору распространения объекта в ES6. - person mpoisot; 27.06.2019
comment
Спасибо, это подтверждение, которое я искал. - person Qortex; 25.10.2019