如何将方法或lambda转换为非lambda proc

时间:2013-04-24 16:15:01

标签: ruby lambda proc

如下面的ruby示例所示,我无法使用lambda创建的Proc来调用参数数量错误的Method,因为它对参数的数量是严格的:

# method with no args
def a; end

instance_eval(&method(:a))
# ArgumentError: wrong number of arguments (1 for 0)

method(:a).to_proc.call(1, 2, 3)
# ArgumentError: wrong number of arguments (3 for 0)

method(:a).to_proc.lambda?
# => true

如何从Proc Proc获取Method来自{{1}}的<{1}}?

3 个答案:

答案 0 :(得分:2)

没有办法做到这一点。

除了参数传递之外,我想知道你对方法中return的期望是什么。它只能以lambda方式行事......

如果你真的必须这样做,你需要建立自己的块,例如

Proc.new{ a }

对于更通用的方法,您必须检查方法的arity并仅传递所需的参数。

答案 1 :(得分:0)

尝试将其包装在非lambda Proc中,如下所示:

l = lambda {|a,b| puts "a: #{a}, b: #{b}" }
p = proc {|a,b| l.call(a,b) }

l.lambda?
#=> true
l.arity
#=> 2
l.call("hai")
#=> ArgumentError: wrong number of arguments (1 for 2)
l.call("hai", "bai", "weee", "womp", "woo")
#=> ArgumentError: wrong number of arguments (5 for 2)

p.lambda?
#=> false
p.arity
#=> 2
p.call("hai")
#=> a: hai, b: 
p.call("hai", "bai", "weee", "womp", "woo")
#=> a: hai, b: bai

答案 2 :(得分:0)

Lambda转换为Proc

这是一个解决方法,它在lambda中包含methodProc调用,并使用splat处理任意数量的参数:

def lambda_to_proc(lambda)
  Proc.new do |*args|
    diff = lambda.arity - args.size
    diff = 0 if diff.negative?
    args = args.concat(Array.new(diff, nil)).take(lambda.arity)

    lambda.call(*args)
  end
end

无论传递的参数数量多少,这都会有效;将删除额外的参数,nil将替换缺少的参数。

示例:

# lambda with two args
some_lambda = -> (a,b) { [a, b] }

# method with no args
def some_method; "hello!"; end

lambda_to_proc(some_lambda).call(5)
# => [5, nil]

lambda_to_proc(method(:some_method)).call(1,2,3)
# => "hello!"

注意: 没有直接的方法将lambda或方法调用转换为proc。这只是一种解决方法,显然比实际交易慢(因为将一个调用包装在另一个调用中)。