例の \en
の問題の解答。
e-TeX 拡張エンジン上の plain TeX または LaTeX において、以下の要件を満たすように制御綴
\en
を定義せよ。
\en
は (La)TeX の寸法指定における「単位」の位置に書くことができる。- そして、「現在の
0.5em
」の長さを表す。すなわち、1\en
と0.5em
は常に同じ長さを表す。
もちろん、次のものは不正解である。
\newdimen\en \en=0.5em
何故なら、これだと「em 値の解釈(絶対値への変換)」が \en
に代入する時に起こってしまって、その後変わらないからである。だから、この後(fontdef トークンが実行されて)現在フォントが変わると、そこではもはや \en
は「現在の 0.5em」とは一致しなくなる。((とすると、「\font
プリミティブにフックを入れて……」という方向を考えたくなるかも知れないので、補足条件を入れてこちらを排除しておいた。))といって、
\def\en{0.5em}
という単純極まるマクロで定義すると、確かに \en
はいつでも「現在の 0.5em」となるが、2\en
は当然ながら \en
の 2 倍ではなく 20.5em
となるのでこれもダメである。
e-TeX 前提の出題であるが、必要な e-TeX の機能は、割と有名なアレである。すなわち、正解はコレ。
\def\en{\dimexpr 0.5em\relax}
これだけでよい。
\def\en{\dimexpr 0.5em\relax} \font\cmttX=cmtt10 \cmttX \skip2=-\en plus 1.23\en minus \en \showthe\skip2 %==> -5.24994pt plus 6.4574pt minus 5.24994pt.
これでよい直接の理由は、\dimexpr
の式は、その式の値に等しい「単位」として機能するからである。例えば、
\parindent=6\dimexpr3pt\relax %「\dimexpr3pt\relax」は「単位」となる
とすると、代入されるのは 18.0pt である。
なお、\relax
は \dimexpr
の式の終端を表すのに使われる(値が解釈される際に吸収されその場には残らない)。もし \en
の定義に \relax
がないと、\dimen0=10\en+1pt
のような場合に「+1pt
」が巻き込まれてしまう(本来はそのまま文字として出力されるべき)ので不完全である。
何故 \dimexpr は「単位」になるのか
これは要するに「そういう仕様」なのであって、理由を挙げるのは難しい。ただし、以下の性質を考えて合わせていけば納得し易いかも知れない:
- TeX では「数字で書いた値」と「そうでない値」(「内部値」という)では文法的な扱いが異なる。
例えば、\count@=\p@
とすると\count@
には 1pt の換算値である 65536 が代入される。これに対して、値を直接記述して\count@=1pt
とすると\count@
は 1 となり文字「pt」が出力される。明らかに挙動が違う。 - 「単位」の役割を担える寸法は「内部値」のものだけである。
つまり、「\p@
」は単位になるが、「1pt
」は単位にならない。((「pt
」は純粋な単位で、それ自体は寸法ではない。)) \XXXexpr
の式はそれ自体は展開可能でなく、前に\the
を付けて初めて「その式の値(の数字表記)」に展開される:例えば、\edef\foo{\numexpr6*7}
とした場合、\foo
は「\numexpr6*7
」のままである。\edef\foo{\the\numexpr6*7}
とした場合は、\foo
は「42
」になる。- つまりは、
\numexpr6*7
自体は数字で書いた「42
」とは同等ではない。そして、\the
というのは、「内部値」を「数字で書いた値」に変換する(例えば\the\p@
→1.0pt
)プリミティブである。そう考えると、\XXXexpr
の式はそれ自体は「内部値」と解釈できる。 - 従って、
\dimexpr
の式は「内部値の寸法」なので「単位」として機能する。