GoF in OCaml for Advent Calendar 2012 #5
OCaml Advent Calendar用の記事、第五弾目です。Flyweight パターンやります。
http://ja.wikipedia.org/wiki/Flyweight_%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3
Flyweightパターンはどうやらインスタンスをキャッシュして使いまわす手法のようです。OCamlでキャッシュを使ってインスタンスを使いまわすなら、メモ化関数を作って利用するのが一般的かと思います。
(* メモ化関数. 同じ引数にはキャッシュしておいた値を返す. *) let memoize cache proc args = match try Hashtbl.find cache args with Not_found -> let v = try `Val (proc args) with e -> `Err e in Hashtbl.replace cache args v; (* Hashtblモジュールは破壊的. *) v with `Val x -> x | `Err e -> raise e module Stamp = struct (* Wikipediaの例ではchar型でUNICODE文字を扱っている. *) (* OCamlでUNICODE文字を扱うにはulibとか使う必要があるので、今回は文字列に. *) type t = string let make c = c let print c = print_string c end module StampFactory = struct let cache = Hashtbl.create 10 let clear () = Hashtbl.clear cache (* キャッシュをクリアできるように. *) let get = (* get関数が使うローカル関数を呼ばれる前に作るテクニック. *) (* 最後にfun c -> ..という関数を返している. getが関数である事がよくわかる. *) let mget = memoize cache Stamp.make in fun c -> mget c end (* 使い方 *) let _ = List.iter Stamp.print [StampFactory.get "た"; StampFactory.get "か"; StampFactory.get "い"; StampFactory.get "た"; StampFactory.get "け"; StampFactory.get "た"; StampFactory.get "て"; StampFactory.get "か"; StampFactory.get "け"; StampFactory.get "た"; ]
特にコメントなし。メモ化と呼ぶかFlyweightパターンと呼ぶか、名称の違いかと。
次回に続く! -> http://d.hatena.ne.jp/osiire/20121212