ScalaっぽいパターンマッチをRubyで実装するから始まった 一連のpattern-matchライブラリ関連エントリのおそらく最終章。 任意のオブジェクトに対して正規表現相当のマッチをできるようにしてみたのでその紹介です。
どういうことかと言うと、例えば配列をFixnumの前後で分割したりとか
match([:a, 0, :b, :c]) do with(_[*a, Fixnum, *b]) do a #=> [:a] b #=> [:b, :c] end end
連続した要素の積が12になるところを探したりとか
match([1, 2, 3, 4, 5]) do with(_[*_, *a, *_], guard { a.inject(:*) == 12 }) do a #=> [3, 4] end end
「シーケンス中で連続して同じ値が入っている各箇所について,2 個目以降は削除したシーケンス」を取得したり (前後の値も利用したシーケンス処理 - NyaRuRuが地球にいたころ)とか
def replace_repeated(obj, &block) ret = match(obj, &block) if ret == obj ret else replace_repeated(ret, &block) end rescue PatternMatch::NoMatchingPatternError obj end replace_repeated([1, 2, 4, 4, 3, 3, 4, 0, 0]) do with(_[*a, x, x, *b]) { [*a, x, *b] } end #=> [1, 2, 4, 3, 4, 0]
こういった処理が簡単に書けるようになりました。
先日のRuby開発者会議でパターンマッチを入れたいねみたいな話をしてきたのですが、 せっかくならこのぐらい出来るようになると楽しそうです。