Ruby 2.0正在添加命名参数,如下所示:
def say(greeting: 'hi')
puts greeting
end
say # => puts 'hi'
say(greeting: 'howdy') # => puts 'howdy'
如何在不提供默认值的情况下使用命名参数,以便它们是必需的?
答案 0 :(得分:90)
Ruby 2.0.0中没有特定的方法,但是can do it 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'
答案 1 :(得分:19)
目前(Ruby 2.0.0-preview1)您可以使用以下方法签名:
def say(greeting: greeting_to_say)
puts greeting
end
greeting_to_say
只是一个占位符,如果为命名参数提供参数,则不会对其进行求值。如果你没有传入(仅调用say()
),ruby会引发错误:
NameError: undefined local variable or method `greeting_to_say' for (your scope)
但是,该变量没有绑定任何东西,据我所知,不能从你的方法内部引用。您仍然可以使用greeting
作为局部变量来引用传入的命名参数。
如果您确实要这样做,我建议您使用def say(greeting: greeting)
,以便错误消息引用您为参数指定的名称。我在上面的示例中只选择了不同的一个来说明ruby将在错误消息中使用的内容,因为没有为所需的命名参数提供参数。
切线,如果你打电话给say('hi')
,红宝石会加注ArgumentError: wrong number of arguments (1 for 0)
我认为这有点令人困惑,但它只是预览1。
答案 2 :(得分:11)
结合@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
答案 3 :(得分:3)
怎么样:
def say(greeting: nil)
greeting or raise ArgumentError
puts greeting
end
say # => raises ArgumentError
say(greeting: 'howdy') # => puts 'howdy'
除此之外,它将很难。根据{{3}},关键字参数“是具有默认值的命名参数。”
答案 4 :(得分:3)
在Ruby 2.3中,我可以做到
def say(greeting:)
puts greeting
end
然后用它......
say(greeting: "hello there")