【问题标题】:Find the first proc that doesn't raise an error, and get its return value找到第一个不引发错误的proc,并获取它的返回值
【发布时间】:2012-01-09 04:42:38
【问题描述】:

场景是这样的:您有一些输入要使用几个可能的过程之一进行处理,具体取决于输入本身的某些质量。在您尝试将输入发送给每个人之前,您不会提前知道哪个会起作用。

假设您有一系列可能的 procs 可以尝试。您想要的是找到第一个不会引发错误的过程,并获得它的返回值,最好是一次性完成。如果没有找到 proc,则引发错误。

在 ruby​​ 中你最好如何做到这一点?

到目前为止,我的答案看起来像下面两个之一,但我正在寻找一种更惯用的方式。还有一种将 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

【问题讨论】:

    标签: ruby


    【解决方案1】:

    这是我的解决方案,请注意,rescue 修饰符可以挽救 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
    

    【讨论】:

    • 谢谢,把它放在自己的方法中,这样你就可以使用显式返回,这很有意义,而且更容易理解。
    【解决方案2】:

    您可以将代码缩短为:

    array_of_procs.find {|p| ret=p[input] rescue StandardError next}; raise ArgumentError("...") unless ret
    

    我觉得……

    【讨论】:

      【解决方案3】:

      稍微调整 Joshua 的答案,以便可以在数组本身上调用它,并允许注入“失败”行为:

      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 }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-08-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多