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


вы видели функцию, объявленную так?

def foo a, **b
  ...
end

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

3 166

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

что это двойной Сплат оператор, который доступен с Ruby 2.0.

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

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

my_method(key: "value")

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

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

реальный пример:

например в рельсах 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}