问题
As shown in the ruby example below, I can't call a lambda
with wrong number of arguments as Proc
created from a Method
because it is strict about the number of arguments:
# 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
How do I get a Proc
that is not a lambda from either a Proc
that is or from a Method
?
回答1:
There is no way to do this.
Besides the argument passing, I wonder what you would expect from a return
in the method. It can only behave in lambda
way...
If you really have to do this, you will need to build your own block, e.g.
Proc.new{ a }
For a more generic way, you'll have to check the arity
of the method and pass only the required parameters.
回答2:
Try wrapping it in a non-lambda Proc
, like so:
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
回答3:
Convert Lambda
to Proc
Here's a work-around that wraps a lambda
or a method
call in a Proc
and uses splat to handle any number of arguments:
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
This would always work no matter the number of arguments passed; Extra arguments will be dropped and nil
will replace the missing arguments.
Example:
# 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!"
Note: There is no direct way to convert a lambda or a method call to a proc. This is just a workaround and obviously slower than the real deal (because of wrapping one call in another).
来源:https://stackoverflow.com/questions/16197082/how-to-convert-method-or-lambda-to-non-lambda-proc