Perhaps walking through a better example might help. Let us start with a simple proc:
p = proc { |a, b, c| "a=#{a.inspect}, b=#{b.inspect}, c=#{c.inspect}" }
p[1,2,3]
# "a=1, b=2, c=3"
If we call curry
without the arity
argument then it is pretty clear what's going on:
p.curry # evaluates to a proc
p.curry[1] # and a different proc
p.curry[1][2] # another different proc
p.curry[1][2][3] # "a=1, b=2, c=3"
p.curry[1,2] # yet another proc, hooray for procs!
p.curry[1,2][3] # "a=1, b=2, c=3"
p.curry[1,2,3] # "a=1, b=2, c=3"
So p.curry
gives us a succession of Proc
s by supplying values for the arguments until we have enough to evaluate the original Proc
. Now we start adding arity
values:
p.curry(1) # some proc
p.curry(1)[] # some other proc,
p.curry(1)[1] # "a=1, b=nil, c=nil"
p.curry(1)[1, 2] # "a=1, b=2, c=nil"
p.curry(1)[1, 2, 3] # "a=1, b=2, c=3"
p.curry(2) # a proc
p.curry(2)[] # another proc
p.curry(2)[1] # oh look, a proc, a lovely surprise
p.curry(2)[1][2] # "a=1, b=2, c=nil"
p.curry(2)[1, 2] # "a=1, b=2, c=nil"
p.curry(2)[1, 2, 3] # "a=1, b=2, c=3"
The arity
argument is setting the effective arity of the curried proc; don't bother looking at the real arity – p.curry.arity
, p.curry(1).arity
, ... – since it will always be -1
(i.e. variadic). The result is that p.curry(1)
is sort of like
proc { |a| p[a] }.curry # "change" p's arity to 1 then curry
and p.curry(2)
is sort of like:
proc { |a, b| p[a, b] }.curry # "change" p's arity to 2 then curry
etc. Keep in mind that just because a (non-lambda) proc has arity n
doesn't mean that you have to call it with n
arguments. A proc's arity is more of a suggestion than anything else.
Of course, if you try this chicanery with a lambda then everything goes sideways because lambdas care very much about their arity:
λ = ->(a, b, c) { "a=#{a.inspect}, b=#{b.inspect}, c=#{c.inspect}" }
λ[1] # ArgumentError (wrong number of arguments (given 1, expected 3))
λ.curry[1] # a lambda-proc
λ.curry[1][2][3] # "a=1, b=2, c=3"
λ.curry[1][2, 3] # "a=1, b=2, c=3"
λ.curry(1) # ArgumentError (wrong number of arguments (given 1, expected 3))
λ.curry(2) # ArgumentError (wrong number of arguments (given 2, expected 3))
λ.curry(3) # a lambda-proc that's just like λ.curry