Currying a proc with keyword arguments in Ruby

后端 未结 4 970
刺人心
刺人心 2021-01-17 22:44

Say I have a generic Proc, Lambda or method which takes an optional second argument:

pow = -> (base, exp: 2) { base         


        
4条回答
  •  后悔当初
    2021-01-17 23:32

    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}
    

提交回复
热议问题