PEG を作ってて思ったこと。
Haskell や OCaml に比べて、Ruby は抽象構文木を扱うのがすごく苦手だと思います。一つの大きな理由はパターンマッチがないことですが、それだけでは無いような気がします。
Haskell の場合、
-- 抽象構文木を定義する data AST = Foo AST | Bar AST | Baz -- 処理 1 foo (Foo x) = ... foo (Bar x) = ... foo Baz = ... -- 処理 2 bar (Foo x) = ... bar (Bar x) = ... bar Baz = ... -- 処理 3 bar (Foo x) = ... bar (Bar x) = ... bar Baz = ...
と言うように処理を同じ箇所にまとめて書けますが、Ruby の場合
# 抽象構文木を定義する class AST; end class Foo < AST def initialize(ast); @ast = ast; end # 処理 1 def foo; ...; end # 処理 2 def bar; ...; end # 処理 3 def baz; ...; end end class Bar < AST def initialize(ast); @ast = ast; end # 処理 1 def foo; ...; end # 処理 2 def bar; ...; end # 処理 3 def baz; ...; end end class Baz < AST # 処理 1 def foo; ...; end # 処理 2 def bar; ...; end # 処理 3 def baz; ...; end end
というように各処理が分散してしまいます。open class を使って
# 抽象構文木を定義する class AST; end class Foo < AST def initialize(ast); @ast = ast; end end class Bar < AST def initialize(ast); @ast = ast; end end class Baz < AST; end # 処理 1 class Foo def foo; ...; end end class Bar def foo; ...; end end class Baz def foo; ...; end end # 処理 2 class Foo def bar; ...; end end class Bar def bar; ...; end end class Baz def bar; ...; end end # 処理 3 class Foo def baz; ...; end end class Bar def baz; ...; end end class Baz def baz; ...; end end
と書けば、各処理は一カ所にまとまっていますが、冗長すぎて人間が書ける域を超えています。
何かいい方法はないでしょうか。