gpt4 book ai didi

ruby - 允许 block 处理可变数量参数的干净方法是什么?

转载 作者:数据小太阳 更新时间:2023-10-29 07:29:09 25 4
gpt4 key购买 nike

我以前遇到过这种情况,有些事情告诉我通常处理它的方式不是最干净或最惯用的。

假设我有一个接受一个 block 的函数,该 block 又可以接受 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 似乎很老套。有没有更标准的 Ruby 方法来实现这种事情?

最佳答案

下面是我如何将任意参数传递给 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 接受有限数量的参数,则只传递 args 的前 n 个元素。如果它接受任意数量的参数,则只传递整个参数数组。

lambda 本身将处理 args 不足的情况:

with_arguments &lambda { |foo, bar, baz, *args| }
# ArgumentError: wrong number of arguments (2 for 3)

您可以简单地将两个参数传递给 block :

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

未使用的 block 参数将被丢弃,任何额外的参数将被设置为nil

This is specific to regular blocks and Procs – 如果参数数量错误,lambda 将引发错误。您实际上可以通过调用 Proc#lambda? 来确定是否属于这种情况。

此外,如果您不打算存储该 block ,则简单地使用 yield 会更简洁:

def with_arguments
yield 'foo', 'bar'
end

关于ruby - 允许 block 处理可变数量参数的干净方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10181229/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com