场景是这样的:根据输入本身的某些质量,您需要使用几种可能的过程中的一种来处理某些输入。在您尝试将输入发送给每个人之前,您不会提前知道哪些是可行的。
让我们说你有一系列可能的尝试尝试。你想要的是找到第一个没有引发错误的proc,并获得它的返回值,最好是一次通过。如果没有找到proc,则引发错误。
你最好如何在红宝石中做到这一点?
到目前为止,我的回答看起来像下面两个中的一个,但我正在寻找一种更惯用的方式。还有一种将返回值nil视为有效的方法 - 现在这两种方法都将nil视为错误状态。
(1)
ret = nil
array_of_procs.find do |p|
begin
ret = p[input]
rescue
next
end
end
raise ArgumentError unless ret
(2)
ret = array_of_procs.inject(nil) do |memo, p|
memo = p[input] rescue next
break memo
end
raise ArgumentError unless ret
答案 0 :(得分:4)
这是我的解决方案,请注意救援修改器拯救了StandardError,我认为没有办法在不进行多行阻止的情况下改变它。
def first_valid_result(procs, input)
procs.each { |p| return p[input] rescue nil }
raise ArgumentError
end
这是规范
describe '#first_valid_result' do
let(:error_proc) { lambda { |input| raise } }
let(:procs) { [error_proc] * 2 }
let(:input) { :some_input }
it "returns the input from the first proc that doesnt raise an error" do
procs.insert 1, lambda { |input| input }
first_valid_result(procs, input).should == input
end
it "treats nil as a valid return value" do
procs.insert 1, lambda { |input| nil }
first_valid_result(procs, input).should be_nil
end
it "raises an ArgumentError when no valid proc exists" do
expect { first_valid_result procs, input }.to raise_error ArgumentError
end
end
答案 1 :(得分:0)
您可以将代码缩短为:
array_of_procs.find {|p| ret=p[input] rescue StandardError next}; raise ArgumentError("...") unless ret
我想......
答案 2 :(得分:0)
稍微调整Joshua的答案,以便可以在数组本身上调用它,并允许注入“fail”行为:
module ArrayofProcsMethods
def find_call(*args)
self.each { |p| return p[*args] rescue nil }
block_given? ? yield : raise(ArgumentError, "No valid proc found")
end
end
array_of_procs.extend(ArrayofProcsMethods)
array_of_procs.find_call(input)
array_of_procs.find_call(input) { default_value }
array_of_procs.find_call(input) { raise ProcNotFoundCustomError }