読者です 読者をやめる 読者になる 読者になる

現在の LISP on TeX における環境の実装と問題点

今日は LISP on TeX (https://bitbucket.org/hak7a3/lisp-on-tex) の環境の実装および問題点について.

現状,LISP on TeX *1 の環境は次のようなトークン列になっています.

\keyi{valuei}\keyii{valueii}……\keyn{valuen}

対応を追加する際には,トークン列の先頭にペアを書き込む形になっています.\keyhogeに対応する値を引き出す際は,マクロの書式指定文字列を使ってとリ出すようにするといけます.実際,LoT の初期の(裏)目的のひとつは,「TeX でまともなプログラミングをするためのライブラリが作成できたら嬉しいな」*2だったりしました.その影響で,環境周りの制御綴りには@が入っていなかったりします.

さて,これを使って LoT の環境を構築した時の問題点です.それは

  • set! の実現が困難
  • letrec の実現も困難

の二点です.これは,環境が「ポインタ」的に扱われていないことが要因です.set! では環境を共有しているすべてのものに変更が波及しないといけませんが,クロージャが環境をトークン列として持っているため,どの部分で他と共有しているかを判断できません.また,letrec の場合はクロージャが自身への参照を持つこととなり,環境が無限列となり崩壊します.

例外的に,大域環境は \@globalenv というマクロで定義され「ポインタ」的に扱える関係上,これらの制限がありません*3

解決方法的な何か

値を一段「ポインタ」的な何かに変更

コード例

\keyi{indexi}\keyii{indexii}……

制御綴り [env@indexi]*4が valuei に展開されるように定義します.index は一意になるようなものを振ります.現状の LoT の cons セルがこれに近い実装になっています*5.今の実装をほとんど変えずにいけるけど,いい手だと思えない.

思い切って,リスト構造にする

こんな感じ

\envi -> \envii\keyi{valuei} % next, key, value

このように定義した \envi を持ち歩く.環境への追加に関して少し考慮すべきな点が*6

さーて,どうしようかな……

おまけと言う名の私信 Twitter の反応

やはり,「値」として扱えることがクロージャの実装には嬉しかったりします.id の持ち運びもありだとは思いますが,あまり LaTeX の大域環境を汚したくない(下手をして他のパッケージと衝突したくない)のです.

*1:以下,長いのでLoT

*2:そもそも近代的な言語には程遠いんだから無理という観点は除く

*3:だから,bitbucketのサンプルでは再帰関数が動いている

*4:伝統に則り,制御綴りは四角で囲んで表記してみました.わからない人は \csname env@indexi\endcsname と思っていただけると?

*5:set-car!とかが簡単

*6:実力の無さとも言う