我之前遇到过这种情况,有些东西告诉我我一般处理它的方式不是最干净或最惯用的。
假设我有一个带有一个块的函数,它可以反过来带有1个或2个(比方说)参数。
def with_arguments(&block)
case block.arity
when 1
block.call("foo")
when 2
block.call("foo", "bar")
end
end
with_arguments do |x|
puts "Here's the argument I was given: #{x}"
end
with_arguments do |x, y|
puts "Here are the arguments I was given: #{x}, #{y}"
end
启用arity
似乎非常hacky。有没有更标准的Ruby方法来实现这种事情?
答案 0 :(得分:5)
以下是我如何将任意参数传递给lambda
:
def with_arguments(&block)
args = %w(foo bar)
n = block.arity
block.call *(n < 0 ? args : args.take(n))
end
with_arguments &lambda { |foo| }
with_arguments &lambda { |foo, bar| }
with_arguments &lambda { |*args| }
with_arguments &lambda { |foo, *args| }
with_arguments &lambda { |foo, bar, *args| }
如果n
为负数,则lambda
采用任意数量的参数。准确地(n + 1).abs
这些论点是强制性的。可以使用该信息来决定传递哪些参数。
如果lambda
获取有限数量的参数,则只需传递n
的第一个args
元素。如果它需要任意数量的参数,那么只需传递整个参数数组。
lambda
本身将处理args
不足的情况:
with_arguments &lambda { |foo, bar, baz, *args| }
# ArgumentError: wrong number of arguments (2 for 3)
您可以简单地将两个参数传递给块:
def with_arguments(&block)
block.call 'foo', 'bar'
end
with_arguments { |x| puts x } # y is not used
with_arguments { |x, y| puts x, y } # All arguments are used
with_arguments { |x, y, z| puts x, y, z } # z will be nil
丢弃未使用的块参数,并将任何额外参数设置为nil
。
This is specific to regular blocks and Proc
s - lambda
将引发错误。您可以通过调用Proc#lambda?
此外,如果您不打算存储该块,只需使用yield
就更清晰了:
def with_arguments
yield 'foo', 'bar'
end
答案 1 :(得分:0)
一些解决方案......
答案 2 :(得分:0)
def bar(&block)
puts 'In bar'
block.call(1) if block
puts 'Back in bar'
block.call(1,2) if block
end
1.9.3p392 :043 > bar do |*b| puts b.length end
In bar
1
Back in bar
2