Ruby中的命名参数不起作用?

时间:2013-01-04 08:32:30

标签: ruby ruby-1.9.3

我想知道为什么命名参数不能像我预期的那样工作。

 def my_method(var1, var2 = 1, var3 = 10)
   puts var1, var2, var3
 end

my_method(999, var3 = 123)

输出

999
123
10

而不是(至少,我认为应该如此):

999
1
123

那么,我该怎么做才能使用命名参数?

P.S。当我使用哈希时,它不是我正在寻找的东西:

def my_method(var1, vars = {var2: 1, var3: 10} )
   puts var1, vars[:var2], vars[:var3]
 end

my_method(999, var3: 123)

999

123


my_method(999, var2: 111, var3: 123)

999
111
123



my_method(999)
999
1
10

所以我必须覆盖vars的每个值,或者根本不覆盖它们。有没有更便捷的方式?

5 个答案:

答案 0 :(得分:3)

在ruby my_method(999, var3 = 123)中表示,为var3分配值123并将其传递给my_method

没有命名参数的概念,但是,您可以使用哈希作为my_method的参数,例如:

def my_method(args = {})
   p "#{args[:a]}, #{args[:b]}, #{args[:c]}"
end

然后你可以用:

来调用它
my_method(b: 2, c: 3, a: 1)

将打印1, 2, 3,因为b: 2, c: 3, a: 1被推断为ruby的哈希值。您也可以使用以下方式显式指示哈希:

my_method({b: 2, c: 3, a: 1})

答案 1 :(得分:2)

正如所指出的,Ruby没有关键字参数(但它们是2.0版本)。为了实现您的目标,options哈希是一种非常常见的Ruby习惯用法。

def my_method(var1, options = {})
  var2 = options.fetch(:var2, 1)
  var3 = options.fetch(:var3, 10)

  puts var1, var2, var3
end

my_method(999)
# => 999, 1, 10

my_method(999, var3: 123)
# => 999, 1, 123

my_method(999, var2: 111)
# => 999, 111, 10

my_method(999, var2: 111, var3: 123)
# => 999, 111, 123

my_method()
# => ArgumentError: wrong number of arguments (0 for 1)

请注意,使用options.fetch(:key, default)而不是options[:key] || default通常更可取,因为它允许您明确指定虚假值(即falsenil)。

options = {x: nil, y: false}

x = options[:x] || 42      # sets x to 42
x = options.fetch(:x, 42)  # sets x to nil

y = options[:y] || 43      # sets y to 43
y = options.fetch(:y, 43)  # sets y to false

z = options[:z] || 44      # sets z to 44
z = options.fetch(:z, 44)  # sets z to 44

你甚至可以将一个块传递给fetch,这允许你推迟计算默认值:

options.fetch(:x) { some_expensive_calculation }
# some_expensive_calculation is only called if necessary

答案 2 :(得分:1)

您可以使用此

  def my_method(options = {})
   puts options[:var1] || ''
   puts options[:var2] || ''
   puts options[:var3] || ''
  end

使用

进行通话
my_method(var1:999, var3: 123)

my_method(var1:999)

答案 3 :(得分:1)

你也可以玩这样的东西:

def method(data)
    defaults = {var2: 1, var3: 10}
    (@var1, @var2, @var3) = defaults.merge(data).values_at(:var1, :var2, :var3)
    p @var1, @var2, @var3
end

method(var1: 999, var3: 123)

答案 4 :(得分:1)

Ruby 2.0.0已发布,现在您可以使用命名参数。

def my_method(var1, var2: 1, var3: 10)
   puts var1, var2, var3
end

my_method(999, var3: 123)

结果:

999
1
123

或另一个例子:

def foo(str: "foo", num: 100)
  [str, num]
end

p foo(str: 'buz', num: 1) #=> ['buz', 1]
p foo(str: 'bar') # => ['bar', 100]
p foo(num: 2) # => ["foo", 2]
p foo # => ['foo', 100]
p foo(bar: 'buz') # => ArgumentError