etolisp 進捗 (31) 〜 Undoのサポート
以前,etolisp は「Lisp界のSQLiteを目指す」と書いたことがある。SQLiteは僕が最もクールだと感じたソフトウェアの1つである。その理由にはいくつかある。
一つは,全てにおいてシンプルであること。ライセンス形態はパブリックドメインで,何も考えず商用ソフトに組み込みが可能。ソースファイルは,ヘッダを含めてたったの3ファイルしかないし,特定のライブラリに依存していないので,導入時にやることとは,3つファイルをプロジェクトに追加するだけである。
もう一つは,そもそも,ファイルベースのデータベースには,既に高機能なフリーのライブラリが(BDBとか)存在していて,SQLiteが出るまでは,そこに参入のチャンスがあるなんて,みんな思いつきもしなかった。けれども,大抵のアプリケーション組み込みDBに必要な機能というのは,ものすごく限られていて,今ある実装の10分の1以下の機能で,問題の9割以上は解決できてしまうということを,示してしまった。その目の付けどころ。
今ではブラウザや,AppleのCocoaフレームワーク(Core Data)など,メジャーなデスクトップアプリケーションの保存形式にどんどん採用されている。携帯電話アプリにも採用が進んでいる(iPhone,Symbian,Android)。後発ながら,ここまで潜在的なニーズを開拓して浸透してしまった。
etolispもコンセプトとしては実は,その辺を目指している。etolispはC/C++アプリケーション*1に「組み込み可能」であるだけでなく,アプリケーションのコントローラそのものになるLispエンジンに仕立てることを考えている。本日は,そのための機能の第一弾として,ランタイムのUndo機能を追加した。これは,関数の定義から何からランタイムの「状態」を過去のある状態に戻して,やり直すことができる機能。
デバッグメッセージ付きの実行風景は以下の通り。
% ./etolisp Undo buffer was constructed. etolisp> (setf a 2) => 2 etolisp> (undo-mark) Undo mark was set. (0) => 0 etolisp> (setf a 4) Recording ... ( 0, 1, 244) => 4 etolisp> (setf b 5) Recording ... ( 2, 0, 245) Recording ... ( 3, 0, 245) Recording ... ( 0, 0, 245) => 5 etolisp> (defun square (x) (* x x)) Recording ... ( 2, 0, 246) Recording ... ( 3, 0, 246) Recording ... ( 2, 0, 247) Recording ... ( 3, 0, 247) Recording ... ( 0, 0, 246) => #etolisp> (square 2) => 4 etolisp> (undo 0) Undo! 8 Undo! 7 Undo! 6 Undo! 5 Undo! 4 Undo! 3 Undo! 2 Undo! 1 Undo! 0 => t etolisp> a => 2 ;; (setf a 4) がキャンセルされてる etolisp> b RUNTIME ERROR: symbol (245) b was not found ;; b の定義はまだない 1 error(s) etolisp> (square 2) RUNTIME ERROR: symbol (246) square was not found ;; square の定義もまだない 1 error(s) etolisp> (quit) Undo buffer was destructed. GC::collect() begin... (node=644) 644 nodes (9KB) are deleted. GC::collect() end. (node=0) ----- Leak Check ----- Cons(0) Vals(0) GC::collect() begin... (node=0) GC::collect() end. (node=0)
これは,簡単な割りに役立ちそうな機能。ランタイムをある時点に戻すことができるので,Lispの勉強用にも良いかもね。
次はシリアライズかなぁ。
*1:モチロン.NETも…