如何在Ruby 2.0中传递可选的命名参数

时间:2014-10-27 15:29:19

标签: ruby

有没有办法让参数真正可选,所以我知道它是否是由调用者设置的?

使用nil作为默认值的参数不起作用,因为无法知道调用者是否通过了nil,或者它是参数的默认值。

在命名参数之前,在Ruby 1.9中,使用选项哈希:

def foo(options = {})
  # …
  bar(options)
end

def bar(options = {})      
  puts options.fetch(:name, ‘unknown’) # => 'unknown'
end

使用Ruby 2.0命名参数:

def foo(name: nil)
  # …
  bar(name: name)
end

def bar(name: ‘unknown’)
  # …
  puts name # => nil, since nil is explicitly passed from `foo`
end

4 个答案:

答案 0 :(得分:6)

可能最好的方法是:

def bar(name: nil)
  name ||= 'unknown'
  puts name
end

答案 1 :(得分:1)

目前尚不清楚为什么要知道是否提供了论证。最有用的理由是,您需要一个可选参数。如果这是原因,那么从Ruby 2.1开始,你可以得到你想要的东西。

def foo(a:,b:nil,c:3)
 [a, b, c]
end

foo a: 1, b: 2, c: 3
#=> [1, 2, 3]
foo a: 1, b: 2
#=> [1, 2, 3]
foo a: 1
#=> [1, nil, 3]
foo
#ArgumentError: missing keyword: a

答案 2 :(得分:1)

您可以使用“未定义”值作为默认值,以区别于nil:

Undefined = Object.new.freeze

def foo(a: Undefined)
  puts a
end

foo(a: nil) # => "nil"
foo # => "#<Object:0x000056004b29a058>"

如果您使用dry-rb,则可以使用Dry::Core::Constants::Undefinedsource),它提供了一些附加功能:

Undefined = Dry::Core::Constants::Undefined

def foo(a: Undefined)
  puts a
end

foo(a: nil) # => "nil"
foo # => "Undefined"

答案 3 :(得分:0)

我假设你的例子中你没有在name中使用foo但想要传递它。

您应该将catch all用于命名参数:

def foo(**named)
  # …
  bar(**named)
end

def bar(name: ‘unknown’)
  # …
  puts name
end

foo # => 'unknown'
foo(name: 'baz') # => 'baz'

请注意,这不会干扰其他参数(已命名或未命名),因此如果您有foo的其他参数:

def foo(what, other: 42, **named)