Why lambda#arity always one complements of Proc#arity?

I was reading the official docs
Class: Proc (Ruby 2.1.0). Where
lambda#arity calculstion made me confused. Then from
ruby - Proc.arity vs Lambda.arity - Stack Overflow I
got some clue that lambda#arity always one complements of Proc#arity
?

Code :

(arup~>~)$ pry --simple-prompt

proc { |(x, y), z=0| }.arity
=> 1
lambda { |(x, y), z=0| }.arity
=> -2
proc { |x=0, y=0| }.arity
=> 0
lambda { |x=0, y=0| }.arity
=> -1

Now my direct question is - Why lambda#arity always one complements of
Proc#arity ?

But one example again made my all assumptions are less confident about
lambda#arity calculation. See below :

proc {}.arity
=> 0
lambda {}.arity
=> 0

Where does here lambda#arity not one complements of Proc#arity ?

Here are some other examples:

def m1(x);end
l1 = lambda{|x|}
p1 = proc{|x|}

method(:m1).arity # => 1
l1.arity # => 1
p1.arity # => 1

When there are no optional parameters (and zero or more required
parameters), all three objects report the same arity. This is what
you’d expect in a normal situation.

def m2(x,y=1);end
l2 = lambda{|x,y=1|}
p2 = proc{|x,y=1|}

method(:m2).arity # => -2
l2.arity # => -2
p2.arity # => 1

With an optional/default parameter, the Proc object reports number of
“required” parameters*, while the Method and Lambda objects report the
one’s complement.

def m3(x=1,y=1,z=1);end
l3 = lambda{|x=1,y=1,z=1|}
p3 = proc{|x=1,y=1,z=1|}

method(:m3).arity # => -1
l3.arity # => -1
p3.arity # => 0

Just to demonstrate that -N doesn’t mean “up to N parameters”.

I suppose the logic is:

  1. if arity is positive, there are that many required parameters
  2. if arity is negative,
    a. required parameters = ~arity
    b. there is some (unknown, natural) number of optional parameters

The real question is: why does Proc not report the one’s complement?

  • note: calling them “required” parameters for a proc is a bit
    misleading: proc{|x|x}[] #=> nil

Matthew K. wrote in post #1136252:

Here are some other examples:

With an optional/default parameter, the Proc object reports number of
“required” parameters*, while the Method and Lambda objects report the
one’s complement.

Again exception -

(arup~>Ruby)$ pry --simple-prompt

p = proc { |a,*b,c| }
=> #Proc:0x84f7704@:1(pry)

l = lambda { |a,*b,c| }
=> #<Proc:0x84bbeac@(pry):2 (lambda)>

l.arity
=> -3

p.arity
=> -3

def m(a,*b,c);end
=> nil

method(:m).arity
=> -3

Arup R. wrote in post #1136253:

Again exception -

(arup~>Ruby)$ pry --simple-prompt

p = proc { |a,*b,c| }
=> #Proc:0x84f7704@:1(pry)

l = lambda { |a,*b,c| }
=> #<Proc:0x84bbeac@(pry):2 (lambda)>

l.arity
=> -3

p.arity
=> -3

def m(a,*b,c);end
=> nil

method(:m).arity
=> -3

I don’t know that that’s an exception so much as an inconsistency in
Proc. But again, I don’t know why Proc reports its arity the way it
does in the first place.

It makes sense for the Lambda, because you need to provide values for a
and c, so there are two mandatory parameters. ~2 = -3

l = lambda{|a,*b,c| p a, b, c }
l[1,2] #=> 1, [], 2