在Ruby中将关键字与常规参数混合?

Ruby 2.0支持关键字参数。 我想知道,混合规则和关键字参数的“规则”是什么? 像这样的东西不会工作:

def some_method(a: 'first', b: 'second', c) [a, b, c] end 

但是这将会:

 def some_method(c, a: 'first', b: 'second') [a, b, c] end 

那么为什么在关键字参数(而不是之后)之前join一个正则参数呢?

在网上有一些关于这个(混合关键字和常规参数)? 我似乎无法find任何。

Ruby中参数列表的伪正则expression式(这同样适用于方法,块和lambda文字)是这样的:

 mand* opt* splat? mand* (mand_kw | opt_kw)* ksplat? block? 

这是一个例子:

 def foo(m1, m2, o1=:o1, o2=:o2, *splat, m3, m4, ok1: :ok1, mk1:, mk2:, ok2: :ok2, **ksplat, &blk) Hash[local_variables.map {|var| [var, eval(var.to_s)] }] end method(:foo).arity # => -5 method(:foo).parameters # => [[:req, :m1], [:req, :m2], [:opt, :o1], [:opt, :o2], [:rest, :splat], # [:req, :m3], [:req, :m4], [:keyreq, :mk1], [:keyreq, :mk2], # [:key, :ok1], [:key, :ok2], [:keyrest, :ksplat], [:block, :blk]] foo(1, 2, 3, 4) # ArgumentError: missing keywords: mk1, mk2 foo(1, 2, 3, mk1: 4, mk2: 5) # ArgumentError: wrong number of arguments (3 for 4+) foo(1, 2, 3, 4, mk1: 5, mk2: 6) # => { m1: 1, m2: 2, o1: :o1, o2: :o2, splat: [], m3: 3, m4: 4, # ok1: :ok1, mk1: 5, mk2: 6, ok2: :ok2, ksplat: {}, # blk: nil } foo(1, 2, 3, 4, 5, mk1: 6, mk2: 7) # => { m1: 1, m2: 2, o1: 3, o2: :o2, splat: [], m3: 4, m4: 5, # ok1: :ok1, mk1: 6, mk2: 7, ok2: :ok2, ksplat: {}, # blk: nil } foo(1, 2, 3, 4, 5, 6, mk1: 7, mk2: 8) # => { m1: 1, m2: 2, o1: 3, o2: 4, splat: [], m3: 5, m4: 6, # ok1: :ok1, mk1: 7, mk2: 8, ok2: :ok2, ksplat: {}, # blk: nil } foo(1, 2, 3, 4, 5, 6, 7, mk1: 8, mk2: 9) # => { m1: 1, m2: 2, o1: 3, o2: 4, splat: [5], m3: 6, m4: 7, # ok1: :ok1, mk1: 8, mk2: 9, ok2: :ok2, ksplat: {}, # blk: nil } foo(1, 2, 3, 4, 5, 6, 7, 8, mk1: 9, mk2: 10) # => { m1: 1, m2: 2, o1: 3, o2: 4, splat: [5, 6], m3: 7, m4: 8, # ok1: :ok1, mk1: 9, mk2: 10, ok2: :ok2, ksplat: {}, # blk: nil } foo(1, 2, 3, 4, 5, 6, 7, 8, ok1: 9, mk1: 10, mk2: 11) # => { m1: 1, m2: 2, o1: 3, o2: 4, splat: [5, 6], m3: 7, m4: 8, # ok1: 9, mk1: 10, mk2: 11, ok2: :ok2, ksplat: {}, # blk: nil } foo(1, 2, 3, 4, 5, 6, 7, 8, ok1: 9, mk1: 10, mk2: 11, ok2: 12) # => { m1: 1, m2: 2, o1: 3, o2: 4, splat: [5, 6], m3: 7, m4: 8, # ok1: 9, mk1: 10, mk2: 11, ok2: 12, ksplat: {}, # blk: nil } foo(1, 2, 3, 4, 5, 6, 7, 8, ok1: 9, mk1: 10, mk2: 11, ok2: 12, k3: 13) # => { m1: 1, m2: 2, o1: 3, o2: 4, splat: [5, 6], m3: 7, m4: 8, # ok1: 9, mk1: 10, mk2: 11, ok2: 12, ksplat: {k3: 13}, # blk: nil } foo(1, 2, 3, 4, 5, 6, 7, 8, ok1: 9, mk1: 10, mk2: 11, ok2: 12, k3: 13, k4: 14) # => { m1: 1, m2: 2, o1: 3, o2: 4, splat: [5, 6], m3: 7, m4: 8, # ok1: 9, mk1: 10, mk2: 11, ok2: 12, ksplat: {k3: 13, k4: 14}, # blk: nil } foo(1, 2, 3, 4, 5, 6, 7, 8, ok1: 9, ok2: 10, mk1: 11, mk2: 12, k3: 13, k4: 14) do 15 end # => { m1: 1, m2: 2, o1: 3, o2: 4, splat: [5, 6], m3: 7, m4: 8, # ok1: 9, mk1: 10, mk2: 11, ok2: 12, ksplat: {k3: 13, k4: 14}, # blk: #<Proc:0xdeadbeefc00l42@(irb):15> } 

[注意:强制关键字参数将在Ruby 2.1中引入,其他所有的function已经可用。]

顺序如下:

  • 需要的参数
  • 具有默认值的参数( arg=default_value表示法)
  • 可选参数( *args表示法,有时称为“splat参数”)
  • 必要的论据,再次
  • 关键字参数
    • 可选( arg:default_value表示法,自2.0.0起)
    • 与要求混杂在一起( arg: notation,自2.1.0起)
  • 任意关键字参数( **args符号,自2.0.0起)
  • 块参数( &blk表示法)

例如:

 def test(a, b=0, *c, d, e:1, f:, **g, &blk) puts "a = #{a}" puts "b = #{b}" puts "c = #{c}" puts "d = #{d}" puts "e = #{e}" puts "f = #{f}" puts "g = #{g}" puts "blk = #{blk}" end test(1, 2, 3, 4, 5, e:6, f:7, foo:'bar') { puts 'foo' } # a = 1 # b = 2 # c = [3, 4] # d = 5 # e = 6 # f = 7 # g = {:foo=>"bar"} # blk = #<Proc:0x007fb818ba3808@(irb):24> 

更详细的信息可以从官方的Ruby语法文档中find 。

  1. 带默认值和图示参数的参数必须组合在一起;
  2. Splat参数必须出现在具有默认值的位置参数之后但在关键字参数之前;
  3. 关键字参数必须出现在位置参数之后和双splat参数之前;
  4. 双重图示参数必须出现在块参数之前。

    def foo(a,b = 1,c = 2,* d,e,f:1,g:2,** kwargs,&block)

关键字参数只是一个可选的散列参数,据我所知。

 def some_method(c, a: 'first', b: 'second') 

和…一样

 def some_method(c, { a: 'first', b: 'second' }) // will not compile actually 

Ruby只是将散列语法的最后一个参数解释为散列值。 所以第一个例子不起作用,因为ruby不能理解这样的语法(首先有语法)。