Lazy Patternこのページは最後に更新されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。 last mod. 2008-12-19 (金) 14:30:49
OCaml 3.11からはlazyパターンが導入されました。 まずはOCamlの遅延計算がどのようなものであるか、どのような問題点があったかを簡単に解説します。そして、lazyパターンを導入したことによって、どのように解決されるかを解説します。 おさらい: OCamlの遅延計算OCamlでは一般のプログラミングと同様に正格評価が行われますが、lazyキーワードによって遅延計算を行うことができます。 lazy (do_something ())によって計算が遅延され、 遅延された計算はLazy.forceによって評価されます。一度、評価した式の結果は保存されるので、複数回同じ式が評価されることはありません。 例えば、以下の例ではlet x = lazy (print_endline "hello");;を評価した段階ではhelloが出力されず、Lazy.force x;;を評価すると初めて出力されます。さらに、評価した結果は保存され二回目以降はそれが使われるので、再びLazy.force xを評価してもhelloは出力されません。 # let x = lazy (print_endline "hello");; val x : unit lazy_t = <lazy> # Lazy.force x;; hello - : unit = () # Lazy.force x;; - : unit = () 問題点:パターンマッチが煩雑上記のような仕組みで十分に思えますが、このままではパターンマッチが煩雑になってしまいます。 例えば、(42,lazy [1;2;3])のようなintと遅延されたリストのタプルを考えて見ましょう。そしてこの型に対して、以下のような関数を定義します。
let f = function (0,_) -> true | (_,xs) -> begin match Lazy.force xs with [] -> true | _::_ -> false end わりと複雑になってしまいました。これは、パターンマッチで遅延されたリストの中身を見れないため、いったんLazy.forceをした上で、再度パターンマッチを行わなければならないためです。 lazyパターンの導入この問題を解決するために、lazyパターンが導入されました。 lazyパターンはlazy <パターン>のように、パターンの前にlazyを前置することで利用できます。これは、Lazy.forceしてパターンマッチを行うのと同じ意味になります。 このlazyパターンを用いると、前述の例は以下のように書き直すことができます。 let f = function (0,_) -> true | (_,lazy []) -> true | (_,lazy (_::_)) -> false 先ほどの例と比較して、より簡潔に書くことができました。 まとめOCamlではlazyによって計算を遅延することが可能です。しかし、これまでのOCamlでは、遅延された計算に対してのパターンマッチが煩雑になってしまいました。 3.11で導入されたlazyパターンを用いることで、この遅延された計算に対してのパターンマッチがより簡潔に書けるようになりました。 |