マクロツイーター

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

私が表組中でマクロ展開をしないただ1つの理由

TeX プログラミングにおいて、私は、表組(tabular および array 環境*1)の中でマクロ展開を行うことを徹底的に避けている。その理由は非常に単純で、

何が起こるか分からない
(少なくとも私には)

からである。何が起こるか分からないプログラムはあまり書きたくないものである。

悩ましい例

tabular(array)環境の中で「部分的に横線」を描くための命令 \cline の実装は次のようになっている。

\def\cline#1{\@cline#1\@nil}
\def\@cline#1-#2\@nil{%
  \omit
  \@multicnt#1%
  \advance\@multispan\m@ne
  \ifnum\@multicnt=\@ne\@firstofone{&\omit}\fi
  \@multicnt#2%
  \advance\@multicnt-#1%
  \advance\@multispan\@ne
  \leaders\hrule\@height\arrayrulewidth\hfill
  \cr
  \noalign{\vskip-\arrayrulewidth}}
\def\@multispan#1{%
  \@multicnt#1\relax
  \loop\ifnum\@multicnt>\@ne \sp@n\repeat}
\def\sp@n{\span\omit\advance\@multicnt\m@ne}

これをよく見ると、下請けのマクロ \@cline の中に

よくわからない不思議な \@firstofone

があることに気付く。試しにこの \@firstofone を外して(展開して)みる。

\documentclass[a4paper]{article}
\makeatletter %!!!!!!!!!!!!!!!!!!!!!!!!! begin TeX code
\def\@cline#1-#2\@nil{%
  \omit
  \@multicnt#1%
  \advance\@multispan\m@ne
  \ifnum\@multicnt=\@ne&\omit\fi % \@firstofone を展開した
  \@multicnt#2%
  \advance\@multicnt-#1%
  \advance\@multispan\@ne
  \leaders\hrule\@height\arrayrulewidth\hfill
  \cr
  \noalign{\vskip-\arrayrulewidth}}
\makeatother  %!!!!!!!!!!!!!!!!!!!!!!!!! end TeX code
\begin{document}
\noindent
\begin{tabular}{|c|c|c|}\hline
1&2&3\\\cline{2-3}
1&2&3\\\cline{1-2}
1&2&3\\\cline{1-3}
1&2&3\\\hline
\end{tabular}
\end{document}

すると、案の定、\cline爆発する

! Incomplete \ifnum; all text was ignored after line 20.
<inserted text>
                \fi
l.20 1&2&3\\\cline{1-2}

? 

別の例を挙げる。上掲のコードでマクロ \@multispan の中に \sp@n というマクロがある。これは一度(上掲の通り)定義された後は変更されない。だから、次のように \sp@n を展開しても動作は変わらないように思える。

\def\@multispan#1{%
  \@multicnt#1\relax
  \loop\ifnum\@multicnt>\@ne \span\omit\advance\@multicnt\m@ne\repeat}

しかし実際にこの再定義をやってみると、やっぱり \cline爆発する

Runaway argument?
\ifnum \@multicnt >\@ne
! Forbidden control sequence found while scanning use of \loop.
<inserted text>
                \par
l.22 1&2&3\\\cline{2-3}

? 

これらの現象を以前(かなり昔)に調べてみたことがあるのだが、結局「何をしたらダメなのか」を完全に理解するには至っていない。

結論

というわけで、「tabular や array の中で複雑なマクロを実行している」人がいたら、その人はきっと私よりも凄腕の TeXnician であることに間違いない。

*1:これらの内部実装では TeX の配列(alignment)の機能が用いられている。