マクロツイーター

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

\theナントカ で算術演算する話(1)

何が問題なのか

何故これが“難しい話”なのかというと、カウンタの出力形式を決めるマクロ \theナントカ は、一般には“完全展開可能であることが必須”とされているからである。つまり次のような単純な実装ではダメなのである。

% hoge の出力形式を
% "<piyo+1の算用数字>.<hogeの算用数字>" としたい
\def\thehoge{\count@\c@piyo
  \advance\count@1
  \number\count@.\number\c@hoge}

これが正しくないことは、実際に相互参照を行わせてみれば判る。

\documentclass[a4paper]{article}
\newcounter{piyo}
\newcounter{hoge}[piyo]
\makeatletter %!!!!!!!!!!!!!!! TeX code BEGIN
\def\thehoge{\count@\c@piyo
  \advance\count@1
  \number\count@.\number\c@hoge}
\makeatother  %!!!!!!!!!!!!!!! TeX code END
\begin{document}
hoge = \ref{test} /
\refstepcounter{piyo}% piyo = 1
\refstepcounter{hoge}\label{test}% hoge = 1
hoge = \thehoge
\end{document}

3 回コンパイルした後の出力は以下のようになる。

\label[test} の時点での hoge の出力形式は「2.1」のはず(だから直後の \thehoge はそう出力している)だが、\ref{test} の出力は正しい値になっていない。\thehoge を完全展開可能にすればよいのだが、そうすると \advance が使えないので、「1 を足す」ことができない、というのが“難しい問題”なのである。

この記事では、この類の問題を解決する方針を示す。前提として、「自分は変態ではないので、『1 を足す』操作を TeX 言語のコードで実装する、なんてことは絶対に絶対に絶対にやりたくない」ものとする。

e-TeX 拡張を利用する

e-TeX 拡張の \numexpr などのプリミティブを用いた“値式”は一種の内部値として 扱われるので、\the\number で展開することができる。 これを用いれば、簡単に「完全展開可能な形で算術演算を行う」ことができる。

\def\thehoge{\number\numexpr\c@piyo+1\relax.\number\c@hoge}
intcalc パッケージを利用する

もし「e-TeX 拡張非対応の古いエンジンもサポートしたい」ということであれば、残念ながら変態なコードの使用が必要になる。しかしそれは必ずしも“自分が変態になる必要性”を意味しない。実際、「完全展開可能な形で算術演算を行う」については、既に幾つもパッケージが用意されている。ここでは intcalc パッケージを利用することにしよう。\intcalcInc 命令を利用して次のように書ける。((ちなみに、intcalc パッケージの命令は、e-TeX 拡張が使える場合には変態なマクロでなく真っ当に \numexpr を利用する策に自動的に切り替える。))

\usepackage{intcalc}
\def\thehoge{\intcalcInc{\c@piyo}.\number\c@hoge}

先のテスト文書で実際に確かめてみよう。

\documentclass[a4paper]{article}
\usepackage{intcalc}
\newcounter{piyo}
\newcounter{hoge}[piyo]
\makeatletter %!!!!!!!!!!!!!!! TeX code BEGIN
\def\thehoge{\count@\c@piyo
\def\thehoge{\intcalcInc{\c@piyo}.\number\c@hoge}
\makeatother  %!!!!!!!!!!!!!!! TeX code END
\begin{document}
hoge = \ref{test} /
\refstepcounter{piyo}% piyo = 1
\refstepcounter{hoge}\label{test}% hoge = 1
hoge = \thehoge
\end{document}

一件落着。