47

Ruby 2.0 正在添加命名参数,如下所示:

def say(greeting: 'hi')
  puts greeting
end

say                     # => puts 'hi'
say(greeting: 'howdy')  # => puts 'howdy'

如何在不提供默认值的情况下使用命名参数,以便它们是必需的?

4

5 回答 5

92

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'
于 2013-02-25T23:55:18.280 回答
19

目前(Ruby 2.0.0-preview1)您可以使用以下方法签名:

def say(greeting: greeting_to_say)
  puts greeting
end

Thegreeting_to_say只是一个占位符,如果您向命名参数提供参数,则不会对其进行评估。如果你不传入它(调用 just say()),ruby 将引发错误:

NameError: undefined local variable or method `greeting_to_say' for (your scope)

但是,该变量没有绑定到任何东西,据我所知,不能从您的方法内部引用。您仍将greeting用作局部变量来引用为命名参数传入的内容。

如果您确实要这样做,我建议您使用def say(greeting: greeting),以便错误消息引用您为参数提供的名称。我只在上面的示例中选择了不同的,以说明 ruby​​ 将在您收到的错误消息中使用什么,因为您没有为所需的命名参数提供参数。

切线,如果你跟注say('hi')ruby​​ 会加注ArgumentError: wrong number of arguments (1 for 0),我认为这有点令人困惑,但这只是预览1。

于 2012-11-06T11:58:43.007 回答
12

结合@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

于 2012-11-28T19:31:25.937 回答
5

在 Ruby 2.3 中,我可以做到

def say(greeting:)
  puts greeting
end

然后将其与...

say(greeting: "hello there")
于 2017-07-02T18:05:41.683 回答
3

怎么样:

def say(greeting: nil)
  greeting or raise ArgumentError
  puts greeting
end

say                     # => raises ArgumentError
say(greeting: 'howdy')  # => puts 'howdy'

除此之外,这将是困难的。根据这个网站,关键字参数“是具有默认值的命名参数。”</p>

于 2012-11-06T11:57:20.523 回答