Say I have a generic Proc
, Lambda
or method
which takes an optional second argument:
pow = -> (base, exp: 2) { base
Extending @Stefan answer above as per last comment and in line with his snippet:
def curry(method)
-> (*args, **kargs) {
required = method.parameters.select { |type, _| type == :req }
krequired = method.parameters.select { |type, _| type == :keyreq }
all_args = (required.length <= args.length)
all_keys = krequired.all? { |_, name| kargs.has_key?(name) }
if all_args && all_keys
final_args = (args + kargs.map {|k,v| {k => v} })
method.call(*final_args)
else
-> (*args_, **kargs_) { curry(method)[*args, *args_, **kargs, **kargs_] }
end
}
end
def foo(a1, b1, c1 = 5, a2:, b2:, c2: 50)
{ a1: a1, b1: b1, c1: c1, a2: a2, b2: b2, c2: c2}
end
puts foz = curry(method(:foo)) #=> #
puts bar = foz[6, a2: 60] #=> #
puts bar[1, b2: 10] #=> {:a1=>6, :b1=>1, :c1=>5, :a2=>60, :b2=>10, :c2=>50}
puts baz = bar[1] #=> #
puts baz[10, b2: 30, c2: 40] #=> {:a1=>6, :b1=>1, :c1=>10, :a2=>60, :b2=>30, :c2=>40}