В Ruby 2.6 и ранее синтаксис **argument
был в основном (но не полностью) синтаксическим c сахаром для пройденного га sh. Это было сделано для того, чтобы конвенция передавала переменную ha sh в качестве последнего аргумента методу.
При Ruby 2.7 аргументы ключевых слов, однако, семантически обновлялись и не отображались в ha sh параметр больше. Здесь аргументы ключевого слова обрабатываются из позиционных аргументов.
В Ruby 2.6 и ранее следующие два определения метода, где (по многим аспектам по крайней мере) эквивалентны:
def one(args={})
#...
end
def two(**args)
#...
end
В обоих случаях вы можете передать либо дословно ha sh, либо разделенную ha sh с одинаковым результатом:
arguments = {foo: :bar}
one(arguments)
one(**arguments)
two(arguments)
two(**arguments)
С Ruby 2.7 однако вы должны передать аргументы ключевого слова как таковые (предыдущее поведение все еще работает, но не рекомендуется с предупреждением). Таким образом, вызов two(arguments)
приведет к предупреждению об устаревании в 2.7 и станет недействительным в Ruby 3.0.
Внутренне, аргумент ha sh с разделителями (который передает аргументы ключевого слова в метод) таким образом, получается пустой список аргументов ключевого слова в Ruby 2.7, но позиционный аргумент с пустым Ha sh в 2.6.
Вы можете увидеть, что здесь происходит подробно, проверив, как Ruby интерпретирует аргументы к его public_send
методу. В Ruby 2.6 и более ранних версиях метод имеет следующий интерфейс:
def public_send26(method_name, *args, &block);
p method_name
p args
# we then effectively call
# self.method_name(*args, &block)
# internally from C code
nil
end
При вызове этого метода в Ruby 2.6 как public_send26(:a, **{}
) вы увидите, что аргументы ключевого слова снова " "обернуто" в га sh:
:a
[{}]
С Ruby 2.7 вместо этого у вас есть следующий эффективный интерфейс:
def public_send27(method_name, *args, **kwargs, &block);
p method_name
p args
p **kwargs
# Here, we then effectively call
# self.method_name(*args, **kwargs, &block)
# internally from C code
nil
end
Вы можете видеть, что аргументы ключевого слова являются отдельными обрабатывается и сохраняется как аргументы ключевых слов в Ruby 2.7, а не обрабатывается как обычный позиционный аргумент Ha sh для метода, как это было сделано в Ruby 2.6 и более ранних версиях.
Ruby 2.7 все еще содержит резервное поведение, так что код, ожидающий поведение Ruby 2.6, все еще работает (хотя и с предупреждением). В Ruby 3.0 вам НЕОБХОДИМО строго разделять аргументы ключевых слов и позиционные аргументы. Вы можете найти дополнительное описание этих изменений в новостной записи на ruby -lang.org .