2014-10-27 86 views
2

有没有一种方法可以使参数真正成为可选参数,因此我知道它是否由调用者设置?如何在Ruby 2.0中传递可选的命名参数

使用参数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 
+0

标题和问题似乎不匹配。此外,您的代码显示的内容并不清楚。 – sawa 2014-10-27 15:52:40

+0

我想我的观点是,没有可选参数这样的事情,接下来最好的事情是将默认设置为'nil'。但问题是,显式传递nil作为参数不会调用默认值。 – Kris 2014-10-27 17:01:01

+0

我冒昧地编辑你的标题以更好地反映你的问题。 – 2014-10-27 19:06:07

回答

2

可能是最好的方式是:

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

这是我发布该问题后不久发布的解决方案,我会在接受之前看看是否有其他问题出现。 – Kris 2014-10-27 17:01:38

+0

这样做的行为与使用'fetch'不同,因为显式传递'nil'或'false'的处理方式不同。 – 2014-10-28 16:57:35

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 
+0

我认为问题是'foo(a:1,b:nil)=> [1,nil,3]'和'foo(a:1)=> [1,nil,3]'。有没有办法让'foo'知道它被调用的方式? – 2014-11-01 06:12:25

+0

正确,我明白这是问题所在。解决方案是不给一个默认值(从Ruby 2.1开始是有效的)。通过不给予默认,你坚持提供一个(他们提供的可以是零)。我用'a'参数作为例子。 – 2014-11-03 21:36:50

0

我就从你的例子,你是不是使用fooname,但要沿着传递承担。

你都应该使用catch命名参数,而不是:

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)