何が問題なのか
何故これが“難しい話”なのかというと、カウンタの出力形式を決めるマクロ \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}
一件落着。