マクロツイーター

はてダから移行した記事の表示が崩れてますが、そのうちに直せればいいのに(えっ)

LISP on “plain” TeX

LISP on TeX」こと lisp-on-tex パッケージLaTeX のパッケージであるので、plain TeX 等の「他の TeX フォーマット」では LISP することができない。しかし実際には lisp-on-tex の実装中で LaTeX の機能を用いている箇所は極めて少ない。なので、他の(plain ベースの)フォーマットで動作するように改修するのは容易である。

とりあえず、ラッパーの形で用意してみた。*1

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

*1:パッチを作る方がよいのかも。

*2:なお、やたらと時間がかかるのは、多分、ストリームの実装でメモ化を行ってないため。