Могу ли я потребовать именованные параметры в Ruby 2.x?
Ruby 2.0 добавляет именованные параметры, например:
def say(greeting: 'hi')
puts greeting
end
say # => puts 'hi'
say(greeting: 'howdy') # => puts 'howdy'
Как я могу использовать именованные параметры без указания значения по умолчанию, чтобы они были необходимы?
Ответы
Ответ 1
В Ruby 2.0.0 нет конкретного пути, но вы можете сделать это Ruby 2.1.0 с синтаксисом вроде def foo(a:, b:) ...
В Ruby 2.0.x вы можете применить его, поставив любое выражение, создающее исключение, например:
def say(greeting: raise "greeting is required")
# ...
end
Если вы планируете делать это много (и не можете использовать Ruby 2.1+), вы можете использовать вспомогательный метод, например:
def required
method = caller_locations(1,1)[0].label
raise ArgumentError,
"A required keyword argument was not specified when calling '#{method}'"
end
def say(greeting: required)
# ...
end
say # => A required keyword argument was not specified when calling 'say'
Ответ 2
В настоящий момент (Ruby 2.0.0-preview1) вы можете использовать следующую подпись метода:
def say(greeting: greeting_to_say)
puts greeting
end
greeting_to_say
является просто заполнителем, который не будет оцениваться, если вы предоставите аргумент именованному параметру. Если вы не передадите его (вызов только say()
), рубин вызовет ошибку:
NameError: undefined local variable or method `greeting_to_say' for (your scope)
Однако эта переменная не привязана ни к чему, и насколько я могу судить, нельзя ссылаться изнутри вашего метода. Вы по-прежнему использовали бы greeting
в качестве локальной переменной для ссылки на то, что было передано для именованного параметра.
Если бы вы действительно делали это, я бы рекомендовал использовать def say(greeting: greeting)
, чтобы сообщение об ошибке ссылалось на имя, которое вы указываете на свой параметр. Я только выбрал разные в приведенном выше примере, чтобы проиллюстрировать, какой рубин будет использоваться в сообщении об ошибке, которое вы получите, чтобы не доставлять аргумент требуемому именованному параметру.
Тангенциально, если вы вызываете say('hi')
, ruby поднимет ArgumentError: wrong number of arguments (1 for 0)
, который, я думаю, немного запутан, но это только preview1.
Ответ 3
Объединение решений из @awendt и @Adam,
def say(greeting: ->{ raise ArgumentError.new("greeting is required") }.call)
puts greeting
end
Вы можете сушить это с помощью чего-то вроде:
def required(arg)
raise ArgumentError.new("required #{arg}")
end
def say(greeting: required('greeting'))
puts greeting
end
И комбинируя это с решением @Marc-Andre: https://gist.github.com/rdp/5390849
Ответ 4
Как насчет:
def say(greeting: nil)
greeting or raise ArgumentError
puts greeting
end
say # => raises ArgumentError
say(greeting: 'howdy') # => puts 'howdy'
Кроме этого, это будет сложно. Согласно этот сайт, аргументы ключевого слова "называются параметрами, которые имеют значения по умолчанию."
Ответ 5
В Ruby 2.3 я могу сделать
def say(greeting:)
puts greeting
end