2

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

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

my_method(999, var3 = 123)

输出

999
123
10

而不是(至少,我猜应该是):

999
1
123

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

PS当我使用哈希时,它还不是我想要的:

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或根本不覆盖它们。有没有更方便的方法?

4

5 回答 5

3

在 rubymy_method(999, var3 = 123)​​ 中,分配var3123并将其传递给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})
于 2013-01-04T08:38:12.360 回答
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
于 2013-01-04T09:28:38.200 回答
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)
于 2013-01-04T08:51:26.427 回答
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)
于 2013-01-04T13:56:11.790 回答
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
于 2013-02-25T11:04:08.907 回答