1

是否可以动态地构建一个链block/rescue喜欢这个链,例如从一组符号。下面的代码应该模仿我静态编写的内容:[:f1, :f2, :f3, f4]

  begin
    applyF1()
  rescue
    applyF2()
    begin
      applyF3()
    rescue
      applyF4()
    end
  end

我已经知道如何从符号 ( object.send(message)) 发送构建的消息,所以applyFx不是问题。

4

2 回答 2

1

不确定您真正期望的行为,因为作为@sawa,我认为您也没有applyF{1..4}平等对待。

这个片段展示了如何依次评估几个 lambda,直到其中一个返回非 false 值而不引发任何东西。

如果您想applyF{1..?}成对评估(F1失败时恢复F2,然后尝试使用F3F4在失败时恢复,等等),您可以applyF{2,4,..}始终返回 nil。

#!/usr/bin/env ruby

blocks = {
  a: ->(){ raise "raise" },
  b: ->(){ raise "also raise" },
  c: ->(){ :finished },
  d: ->(){ "won't be executed" },
}

ret = blocks.reduce(nil) do |has_succeeded, (key, lam)|
  has_succeeded ||=
  begin
    puts "trying #{key.inspect}"
    lam.call # when succeed, the lambda should return a non-false value
  rescue => e
    puts "failed with message=<#{e.message}>. trying next"
    nil
    # no else clause here, so
    # if lam.call raises nothing, memo keep its return value, and prevents calling following {lam}s.
    # if something is raised in lam.call, this block evalutes to nil
  end
end

# will print:
# trying :a
# failed with message=<raise>. trying next
# trying :b
# failed with message=<also raise>. trying next
# trying :c

p ret
# => :finished

参考:开始块的值是如何确定的?

于 2013-06-04T00:50:44.390 回答
0

This is the first that comes to my mind:

def rescueChain(*args)
  args.each do |f|
    begin
      <... apply f here ...>
      return  # Exits from the entire function.
    rescue
    end
  end
end

I didn't test it yet.

于 2013-06-03T23:56:20.150 回答