Docs say it's intended, since #arity "returns -n-1, where n is the number of mandatory arguments, with the exception for blocks that are not lambdas and have only a finite number of optional arguments; in this latter case, returns n." A Proc in this case isn't a lambda, so it returns n rather than -n-1. Procs have loose arity, like blocks, unlike lambdas.
@shan (Shannon Skipper) I don't think this documentation definition covers the case described by OP.
proc { |a,| } is not the same as proc { |a| }, and is semantically equivalent of proc { |a,*| }. I think it is reasonable to expect its arity—and, by the way, parameters, would behave as in latter, not as in former.
I think this would be reasonable (and might be useful for metaprogramming code that checks the signature of the passed callable object):
proc{|a|a}.call([1,2,3])#=> [1, 2, 3]proc{|a|}.arity#=> 1proc{|a|}.parameters#=> [[:opt, :a]]proc{|a,*|a}.call([1,2,3])#=> 1proc{|a,*|}.arity#=> -2proc{|a,*|}.parameters#=> [[:opt, :a], [:rest, :*]]proc{|a,|a}.call([1,2,3])#=> 1, like the latterproc{|a,|}.arity#=> 1, should be -2proc{|a,|}.parameters#=> [[:opt, :a]], should be [[:opt, :a], [:rest, :*]]
Though, experimenting a bit more with it, there is a funny edge case:
define_method(:m1,&proc{|a|})define_method(:m2,&proc{|a,*|})define_method(:m3,&proc{|a,|})pmethod(:m1)#<Method: Object#m1(a)>pmethod(:m2)#<Method: Object#m2(a, *)>pmethod(:m3)#<Method: Object#m3(a)> --- like 1, not like 2
...which is probably related to reported arity/parameters.