clojureのシリアライズ系ライブラリを試した
要は、ゲームの進行状況を保存する為に、各変数の内容を文字列もしくはバイト列に読み書きしたい為。
今まではedn( http://clojure.github.io/clojure/clojure.edn-api.html )をそのまま使っていたが、これはjava arrayやatom, ref等をサポートしておらず、副作用バリバリに変数内容を変更する事が多いゲーム向きではなかったので。
チェック内容は以下の通り。
- java arrayが読み書きできるか。特にobject-arrayの中身がS式だった場合でも正しく扱えているか
- atom, refが読み書きできるか(ただし今回の調査では面倒なのでatomしか調べてない)
- オブジェクトのトポロジカル構造が維持されるか
- これは要するに、以下のようなオブジェクトをwrite/readした後に、carとcadrが同じオブジェクトとして再現されるか、という事。
(let [a (int-array [1 2])] (list a a))
以下を試した。
- edn (org.clojure/clojure "1.5.1") http://clojure.github.io/clojure/clojure.edn-api.html
- nippy (com.taoensso/nippy "2.5.2") https://github.com/ptaoussanis/nippy
- fressian (org.clojure/data.fressian "0.2.0") https://github.com/clojure/data.fressian
- carbonite (com.twitter/carbonite "1.3.2") https://github.com/sritchie/carbonite
- Deep-Freeze (deep-freeze "1.2.2-SNAPSHOT") https://github.com/halgari/deep-freeze
- Cheshire (cheshire "5.3.1") https://github.com/dakrone/cheshire
感想:
- どのシリアライザもトポロジカル構造を再現してくれない!Common LispやSchemeなら大体は標準完備なのに…
セーブロードで利用したいという要望に対する結論:
- どのシリアライザもトポロジカル構造を再現してくれない為、参照構造をそのままセーブデータとして書き込む事ができない。よって、マップ&キーワードもしくは配列&インデクス値を使い、間接的に参照を保持せざるをえない。超めんどい。
- atom類については、Deep-Freezeは標準対応しているが、Deep-Freezeは他に問題が多いので却下したい。そして他には簡単に扱えるものはないので、atom類は使用しないで、参照を保持したい時はobject-arrayを使うようにすべき、という結論に。
- とは言え、上記の通り、そもそも「参照を直に保存できない」という結論が出ている為、基本的にはインデクス値指定を多用すると思われるので、こっちについてはそれほど大きな影響はないと思う。
- なお、変数そのものを更新したい場合は、alter-var-rootで直に更新する。
- とりあえず「そのままjava arrayが扱える」グループの中でも、一番扱いやすかったnippyを採用しようと思う。
参考にしたリンク/関連リンク: