「LISP on TeX」こと lisp-on-tex パッケージ は LaTeX のパッケージであるので、plain TeX 等の「他の TeX フォーマット」では LISP することができない。しかし実際には lisp-on-tex の実装中で LaTeX の機能を用いている箇所は極めて少ない。なので、他の(plain ベースの)フォーマットで動作するように改修するのは容易である。
とりあえず、ラッパーの形で用意してみた。*1
- tcplainlot.tex (gist/zr-tex8r)
lisp-on-tex パッケージをインストールした状態で、TeX 文書中で
\input tcplainlot
を実行すると、lisp-on-tex の機能が使えるようになる。
これを使って、「例の Hamming 数列のアレ」をやってみる。
[test-tcplainlot.tex]
%% This is a plain TeX document. \input tcplainlot.tex % LISP on plain TeX! \lispinterp{% %% stream something (\define \stnil ()) (\define \stnilQ \nilQ) (\define \stcar \car) (\define \stcdr (\lambda (\s) ((\cdr \s)))) (\defmacro \stcons (\lambda (\x \s) % special-form (\cons (\quote \cons) (\cons \x (\cons (\cons (\quote \lambda) (\cons () (\cons \s ()))) ()))))) (\define \stmap (\lambda (\proc \s) (\lispif (\stnilQ \s) \stnil (\stcons (\proc (\stcar \s)) (\stmap \proc (\stcdr \s)))))) (\define \stmergeiseq (\lambda (\sx \sy) (\lispif (\stnilQ \sx) \sy (\lispif (\stnilQ \sy) \sx (\let ((\x (\stcar \sx)) (\y (\stcar \sy))) (\lispif (\< \x \y) (\stcons \x (\stmergeiseq (\stcdr \sx) \sy)) (\lispif (\< \y \x) (\stcons \y (\stmergeiseq \sx (\stcdr \sy))) (\stcons \x (\stmergeiseq (\stcdr \sx) (\stcdr \sy)))))))))) %% (\stprinthead <stream> <n>) % Prints the first n items of the stream. (\define \stprinthead (\lambda (\s \n) (\lispif (\< \n :1) () (\begin (\texprint (\stcar \s)) (\texprint ' ') (\stprinthead (\stcdr \s) (\- \n :1)))))) %% (\intseq <n>) % The integer sequence starting from n. (\define \intseq (\lambda (\n) (\stcons \n (\intseq (\+ \n :1))))) %% (\scale <n>) (\define \scale (\lambda (\n) (\lambda (\x) (\* \x \n)))) %% \hamming : The Hamming something. (\define \hamming (\stcons :1 (\stmergeiseq (\stmap (\scale :2) \hamming) (\stmergeiseq (\stmap (\scale :3) \hamming) (\stmap (\scale :5) \hamming))))) } %--------------------------------------- First 50 items in the Hamming sequence are: \lispinterp{(\stprinthead \hamming :50)} \bye
これを tex とか pdftex でコンパイルすると以下の出力が得られる。*2