Ruby 1.9.3和Ruby 2.0的arity的对比
2013年4月23日 00:25
一直感觉arity这个属性的算法提及的很少(虽然arity是个数学概念,但是简单的数学概念显然无法满足Ruby的复杂的需求),即使在Ruby-doc的Method和Proc中也是如此。
Returns an indication of the number of arguments accepted by a method. Returns a nonnegative integer for methods that take a fixed number of arguments. For Ruby methods that take a variable number of arguments, returns -n-1, where n is the number of required arguments. For methods written in C, returns -1 if the call takes a variable number of arguments.
这篇Ruby 2.0的文档里面仅仅提到了几种最简单的情况,还远远算不上复杂,现在我这里列出了比文档里更多的例子,以此来分析arity的行为。
测试代码是这样的:
p proc {}.arity p proc {||}.arity p proc {|a|}.arity p proc {|a,b|}.arity p proc {|a,b,c|}.arity p proc {|*a|}.arity p proc {|a,*b|}.arity p proc {|a,*b, c|}.arity p proc {|x = 0, *args|}.arity p proc {|x=0, y=0, *args|}.arity p proc {|x, y=0, *args|}.arity p proc {|(x, y), z=0, *args|}.arity p proc {|a, b = 1, *c, d|}.arity p proc {|a = 1, b = 1, *c, d|}.arity p proc { |x = 0| }.arity p lambda { |a = 0| }.arity def f(a = 0) end; p method(:f).arity p proc { |x=0, y| }.arity p lambda { |x=0, y| }.arity def f(x = 0, y) end; p method(:f).arity p proc { |x=0, y=0| }.arity p lambda { |x=0, y=0| }.arity def f(x=0, y=0) end; p method(:f).arity p proc { |x, y=0| }.arity p lambda { |x, y=0| }.arity def f(x, y=0) end; p method(:f).arity p proc { |(x, y), z=0| }.arity p lambda { |(x, y), z=0| }.arity def f((x, y), z=0) end; p method(:f).arity
然后是结果对比:
code | ruby-1.9.3 | ruby-2.0.0 |
---|---|---|
p proc {}.arity | 0 | 0 |
p proc {||}.arity | 0 | 0 |
p proc {|a|}.arity | 1 | 1 |
p proc {|a,b|}.arity | 2 | 2 |
p proc {|a,b,c|}.arity | 3 | 3 |
p proc {|*a|}.arity | -1 | -1 |
p proc {|a,*b|}.arity | -2 | -2 |
p proc {|a,*b, c|}.arity | -3 | -3 |
p proc {|x = 0, *args|}.arity | -1 | -1 |
p proc {|x=0, y=0, *args|}.arity | -1 | -1 |
p proc {|x, y=0, *args|}.arity | -2 | -2 |
p proc {|(x, y), z=0, *args|}.arity | -2 | -2 |
p proc {|a, b = 1, *c, d|}.arity | -3 | -3 |
p proc {|a = 1, b = 1, *c, d|}.arity | -2 | -2 |
p proc { |x = 0| }.arity | 0 | 0 |
p lambda { |a = 0| }.arity | 0 | -1 |
def f(a = 0) end; p method(:f).arity | -1 | -1 |
p proc { |x=0, y| }.arity | 0 | -1 |
p lambda { |x=0, y| }.arity | 0 | -2 |
def f(x = 0, y) end; p method(:f).arity | -2 | -2 |
p proc { |x=0, y=0| }.arity | 0 | 0 |
p lambda { |x=0, y=0| }.arity | 0 | -1 |
def f(x=0, y=0) end; p method(:f).arity | -1 | -1 |
p proc { |x, y=0| }.arity | 1 | 1 |
p lambda { |x, y=0| }.arity | 1 | -2 |
def f(x, y=0) end; p method(:f).arity | -2 | -2 |
p proc { |(x, y), z=0| }.arity | 1 | 1 |
p lambda { |(x, y), z=0| }.arity | 1 | -2 |
def f((x, y), z=0) end; p method(:f).arity | -2 | -2 |
由这一对比结果,可以清楚的看到:
- 对于proc而言,如果参数中没有可变长参数(比如*args之类的),则在1.9.3中,arity取决于从左往右没有默认值的参数的数量。2.0.0中取决于整个参数列表中没有默认值的参数数量。
- 如果有可变长参数,则如果n为整个参数列表中没有默认值的参数数量,arity为-n - 1。
- 对于lambda而言,可以看到,在1.9.3中情况与proc总是一致的。而在2.0.0中,如果存在有默认值的参数,则如果n为整个参数列表中没有默认值的参数数量,arity = -n -1。否则就等于参数数量。
- 对于method而言,无论1.9.3还是2.0.0,均与2.0.0中的lambda一致(准确的应该说是lambda在2.0.0中与method保持一致)。
- 额外的&block不影响到arity的值。
大致结果就是如此了,如果有误,请务必留言告知,谢谢。