PHPの@演算子的なもの
http://d.hatena.ne.jp/gnarl/20080820/1219226223
例外かどうかを判断するのが誰であるべきかという話はおいといて、try-catch系の構文は、成功/失敗の二値が知りたいだけの場合でもあの長ったらしい構文を使わないといけないのがうざいなーとは常々思っていました。
Rubyだとこんな感じのブロックを取る演算があればいい?
class X @@exn = nil # 直前に握り潰した例外 # ブロックを評価し、例外が起きた場合は握り潰す def self.ignore_exception(recover_from=Exception) return nil if @@exn && !(@@exn.kind_of? recover_from) begin r = yield @@exn @@exn = nil r rescue => e @@exn = e nil end end end def _x(*a, &b) X.ignore_exception(*a, &b) end def parseint(s) if /^\d+$/ =~ s s.to_i else raise ArgumentError, "illegal format" end end parseint("123") #=> 123 _x{parseint("123")} #=> 123 parseint("hoge") #=> 例外 _x{parseint("hoge")} #=> nil が返る
_x{ ... } でくくると、中で例外が発生した場合は全て nil になります。(追記: これに近い働きをする rescue修飾子なんてものもありました。完全に忘れてました(^^;)
一般的には例外握り潰すとかマナー悪いもいいところですが、どんな例外でもひとつでも起きたら全部同じ処理っていうケースもよくあります。
if _x{ f(xxx) } // 成功したら... else // 失敗したら... end
特に長いメソッドチェーンでいちいちnilチェックしなくて済むのがうれしい。
result = _x{ tbl['xxx'][123][456] } result = _x{ f(xxx).g(yyy).h(zzz) }
これはMaybeモナドっぽいと言えるかもしれない。
また ||演算子を ||-> 的に使えます(シングルスレッド限定)。
# 1番目で HogeError が起きた場合に限り, 2番目が実行される。 result = _x{...} ||_x(HogeError){|e|...} ||_x{...}
false や nil を途中で値として返したいときとか困りますがっ! (=> 追記:エラーモナド in Ruby)
たぶん計算をショートカットする二項演算というのが && や || の専売特許なのがあまり良くなくて、左辺のパターンマッチングでショートカットするかどうかを決められるような二項演算子定義機能があるとうれしい。