Ruby throwの使いどころ

例外ではなく、制御構造の話。

Effective Ruby

Effective Ruby

項目27 スコープから飛び出したい時にはraiseではなくthrowを使おう

catchとthrowはgotoの安全バージョン。

StopIterationを使った例

begin
  @characters.each do |character|
    @colors.each do |color|
      if player.valid?(character, color)
        raise(StopIteration)
      end
    end
  end
rescue StopIteration
  # ...
end

catchを使うと

よりsimpleに書ける。throwの第二引数に値を渡せるのも良いね。これ知らなかったな。

match = catch(:jump) do
  @characters.each do |character|
    @colors.each do |color|
      if player.valid?(character, color)
        throw(:jump, [charcter, color])
      end
    end
  end
end

覚えておくべき事項

  • 複雑な制御フローが必要な時には、raiseではなく、throwを使うようにしよう。throwを使うと、ボーナスとしてスタックの上にオブジェクトを送ることができる。catchの戻り値はそのオブジェクトだ。
  • できる限り単純な制御構造を使おう。catchとthrowの組み合わせは、単純にreturnでスコープから抜け出すメソッドとそれに対する呼び出しで置き換えられることが多い。