Ответы:
В 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}
на консоль.
Точно так же, как оператор одиночного сплата захватывает все обычные аргументы, но вместо массива вы получаете хеш .
Пример из жизни:
Например, в 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}
opts = {d: 40, e: 50}
, тоfoo 10, opts, f: 60
назначит{f: 60}
кc
, в то время какfoo 10, **opts, f: 60
будет назначать{d: 40, e: 50, f: 60}
. Для достижения второго эффекта ранее вы должны были быmerge
явно использовать массивы.