Ruby中的默认值的可选参数

时间:2013-05-01 16:56:59

标签: ruby named-parameters optional-arguments

我想创建一个具有默认值

的可选参数的函数
def my_function(a = nil, b=nil, c=500)

end

并使用我想要指定的参数调用该函数

my_function(b=100)

如何在Ruby 1.9.2中实现这一目标?

3 个答案:

答案 0 :(得分:24)

参数绑定到这样的参数:

  1. 只要参数列表的开头有未绑定的必需参数,就从左到右绑定参数
  2. 只要参数列表末尾有未绑定的必需参数,从右到左绑定参数
  3. 任何剩余的参数都绑定到从左到右的可选参数
  4. 任何剩余的参数都会被收集到一个数组中并绑定到splat参数
  5. 一个块被包装成Proc并绑定到块参数
  6. 如果有任何未绑定参数或剩余参数,raiseArgumentError
  7. 以下是一个例子:

    def foo(mand1, mand2, opt1=:opt1, opt2=:opt2, *splat, mand3, mand4, &block)
      p local_variables.map {|v| "#{v} = #{eval(v.to_s)}" }
    end
    
    foo 1, 2, 3
    # ArgumentError: wrong number of arguments (3 for 4+)
    
    foo 1, 2, 3, 4
    # mand1 = 1
    # mand2 = 2
    # opt1 = opt1
    # opt2 = opt2
    # splat = []
    # mand3 = 3
    # mand4 = 4
    # block = 
    
    foo 1, 2, 3, 4, 5
    # mand1 = 1
    # mand2 = 2
    # opt1 = 3
    # opt2 = opt2
    # splat = []
    # mand3 = 4
    # mand4 = 5
    # block = 
    
    foo 1, 2, 3, 4, 5, 6
    # mand1 = 1
    # mand2 = 2
    # opt1 = 3
    # opt2 = 4
    # splat = []
    # mand3 = 5
    # mand4 = 6
    # block = 
    
    foo 1, 2, 3, 4, 5, 6, 7
    # mand1 = 1
    # mand2 = 2
    # opt1 = 3
    # opt2 = 4
    # splat = [5]
    # mand3 = 6
    # mand4 = 7
    # block = 
    
    foo 1, 2, 3, 4, 5, 6, 7, 8 do end
    # mand1 = 1
    # mand2 = 2
    # opt1 = 3
    # opt2 = 4
    # splat = [5, 6]
    # mand3 = 7
    # mand4 = 8
    # block = #<Proc:0x007fdc732cb468@(pry):42>
    

    因此,正如您可以从上面的步骤3和示例中看到的那样,您无法执行此操作,因为可选参数是从左到右绑定的,但您要指定中间参数。

    请注意,这会对API设计产生影响:您应该设计参数列表,使得最“不稳定”的可选参数(即用户最有可能想要提供的参数)在左侧最远。

    Ruby 2.0现在有关键字参数,这正是您所寻找的:

    def foo(m1, m2, o1=:o1, o2=:o2, *s, m3, m4, key1: :key1, key2: :key2, **keys, &b)
      puts local_variables.map {|v| "#{v} = #{eval(v.to_s)}" }
    end
    
    foo 1, 2, 3
    # ArgumentError: wrong number of arguments (3 for 4+)
    
    foo 1, 2, 3, 4
    # m1 = 1
    # m2 = 2
    # o1 = o1
    # o2 = o2
    # s = []
    # m3 = 3
    # m4 = 4
    # key1 = key1
    # key2 = key2
    # b = 
    # keys = {}
    
    foo 1, 2, 3, 4, 5
    # m1 = 1
    # m2 = 2
    # o1 = 3
    # o2 = o2
    # s = []
    # m3 = 4
    # m4 = 5
    # key1 = key1
    # key2 = key2
    # b = 
    # keys = {}
    
    foo 1, 2, 3, 4, 5, 6
    # m1 = 1
    # m2 = 2
    # o1 = 3
    # o2 = 4
    # s = []
    # m3 = 5
    # m4 = 6
    # key1 = key1
    # key2 = key2
    # b = 
    # keys = {}
    
    foo 1, 2, 3, 4, 5, 6, 7
    # m1 = 1
    # m2 = 2
    # o1 = 3
    # o2 = 4
    # s = [5]
    # m3 = 6
    # m4 = 7
    # key1 = key1
    # key2 = key2
    # b = 
    # keys = {}
    
    foo 1, 2, 3, 4, 5, 6, 7, 8
    # m1 = 1
    # m2 = 2
    # o1 = 3
    # o2 = 4
    # s = [5, 6]
    # m3 = 7
    # m4 = 8
    # key1 = key1
    # key2 = key2
    # b = 
    # keys = {}
    
    foo 1, 2, 3, 4, 5, 6, 7, 8, key1: 9
    # m1 = 1
    # m2 = 2
    # o1 = 3
    # o2 = 4
    # s = [5, 6]
    # m3 = 7
    # m4 = 8
    # key1 = 9
    # key2 = key2
    # b = 
    # keys = {}
    
    foo 1, 2, 3, 4, 5, 6, 7, 8, key1: 9, key2: 10
    # m1 = 1
    # m2 = 2
    # o1 = 3
    # o2 = 4
    # s = [5, 6]
    # m3 = 7
    # m4 = 8
    # key1 = 9
    # key2 = 10
    # b = 
    # keys = {}
    
    foo 1, 2, 3, 4, 5, 6, 7, 8, key1: 9, key2: 10, key3: 11
    # m1 = 1
    # m2 = 2
    # o1 = 3
    # o2 = 4
    # s = [5, 6]
    # m3 = 7
    # m4 = 8
    # key1 = 9
    # key2 = 10
    # b = 
    # keys = {:key3=>11}
    
    foo 1, 2, 3, 4, 5, 6, 7, 8, key1: 9, key2: 10, key3: 11, key4: 12 do end
    # m1 = 1
    # m2 = 2
    # o1 = 3
    # o2 = 4
    # s = [5, 6]
    # m3 = 7
    # m4 = 8
    # key1 = 9
    # key2 = 10
    # b = #<Proc:0x007fdc75135a48@(pry):77>
    # keys = {:key3=>11, key4=>12}
    

答案 1 :(得分:8)

所以你试图实现关键字参数?这应该是Ruby 2.0中的一个新功能,但您可以尝试使用参数哈希在1.9.x中模拟它。 Here's a post讨论了如何实现这一点,它提供了以下代码示例:

def foo(options = {})
  options = {bar: 'bar'}.merge(options)
  puts "#{options[:bar]} #{options[:buz]}"
end

foo(buz: 'buz') # => 'bar buz'

答案 2 :(得分:6)

你不能在Ruby中这样做(或类似的东西)&lt; 2.0。你能做的最好的是:

def my_function(h = {})
  h[:c] ||= 500
  # Use h[:a], h[:b], h[:c]
  ...
end

my_function(b: 100)