マクロツイーター

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

TeX の構文規則がフリーフォーマットでないことがよくわかる話(1)

TeX 言語の構文規則が「フリーフォーマットでない」――すなわち、空白や改行に対する注意を怠ってはいけない――ことは、すでに以前の記事で説明した。この話題に関して、(某アドベントカレンダーでおなじみの)neruko3114 さんが非常に解りやすい例を含む発表を「第36回長岡IT開発者勉強会」で行っていたので紹介する。

9 枚目のスライド。*1

わかりやすい「アウトな空白」の例

そして、この −2 枚後のスライドで「バグ例」が紹介されている。

TeX に慣れている人なら、\factorial の定義本体の 6 行目の } の後の「改行による空白」が「アウト」であることはすぐに気付くであろう。実際に試してみよう。

\documentclass{article}
\makeatletter
% スライド掲載のコードを"そのまま"書いた
\newcount\@m
\newcount\@k

\def\factorial#1{%
  \@m = 1 \relax
  \@k = 1 \relax
  \@whilenum \@m < #1 \do {%
    \advance \@m 1 \relax
    \multiply \@k \@m \relax
  }
  \the\@k
}
\makeatother
\begin{document}
% 直接"720"を書いた
The factorial of 6 is 720.\par
% \factorial を用いて出力した
The factorial of 6 is \factorial{6}.\par
% \factorial の引数の値(6)をカウンタを介して渡した例
\newcounter{myVal}
\setcounter{myVal}{6}
The factorial of \arabic{myVal} is \factorial{\value{myVal}}.\par
\end{document}

期待する結果としては、1 番目と 2 番目は全く同じ出力であるべきだが実際には \factorial を用いた出力には余計な空きが入っている。この理由は、先ほど述べた「アウトな空白トークン」が結果の「720」を出力する前に実行されてしまっているからに他ならない。

わかりにくい「アウトな空白」の例

ここで話は終わらない。実は、当該のコードはもう一つ空白に関する問題を抱えている。それを突いたのが 3 番目の例である。ここでは、引数の値「6」を直接数字で書くのではなく一度カウンタ myVal に代入して、カウンタ値参照(\value{myVal})((\value{myVal} を使うとカウンタの値を TeX の「内部値」として扱うことができる。もっと端的にいうと、\value{myVal}\c@myVal に展開される。一方で、\arabic{myVal} はカウンタの値を「数字に展開する」ためのもので、こちらは\the\c@myVal に展開される。))の形で \factorial 命令に渡している。常識的に考えると、この場合でも 1 番目(あるいは 2 番目?)と同じ出力をしないといけないはずだが((ただし、LaTeX における命令 \factorial の「仕様」として「引数は数字で与えなければならない」と規定されているならば、このようなケースは(「仕様外」なので)考える必要はなくなる。もしそういう規定が明示されていない場合はカウンタ参照での入力もサポートすべきであるというのは私の意見である。))、実際にはこのケースでは大量の空きが発生してしまっている。この原因が何であるかを調べるのは、TeX 言語初級者への課題としておこう。

*1:この 2 枚後のスライドで「フリーフォーマットでない」ことについてのより詳しい解説がある。