完全展開可能なナベアツ
「TeX でナベアツ」問題については、これまでに Web 上にいくつか回答が公開されている。その多くは完全な正解であるが、それは何れも「脆弱(fragile)」である。すなわち、
\edef\result{\NabeAzz{40}} \result
のように一回 \edef
で「展開」した後で実行するということはできない。そこで、「完全展開可能」なナベアツを実装しようというのが今回の出題の趣旨である。
以下の仕様を満たすマクロ \NabeAzzX を実装せよ。
\NabeAzzX{<n>}
を完全に展開すると、1 から n までの整数について、その 10 進表記の数字列を空白トークンで区切ったものに展開される。ただし、3 の倍数または 10 進表記に数字 3 を含む整数については、{\AhoFont <整数>}
という形になる。- ここで、制御綴
\AhoFont
は展開不能であると仮定する。- 例えば、
\edef\result{\NabeAzzX{40}}
を実行すると、\result
は以下のトークン列に展開されるマクロになる。1 2 {\AhoFont 3} 4 5 {\AhoFont 6} 7 8 {\AhoFont 9} 10 11 {\AhoFont 12} {\AhoFont 13} 14 {\AhoFont 15} 16 17 {\AhoFont 18} 19 20 {\AhoFont 21} 22 {\AhoFont 23} {\AhoFont 24} 25 26 {\AhoFont 27} 28 29 {\AhoFont 30} {\AhoFont 31} {\AhoFont 32} {\AhoFont 33} {\AhoFont 34} {\AhoFont 35} {\AhoFont 36} {\AhoFont 37} {\AhoFont 38} {\AhoFont 39} 40
ここでトークン \AhoFont
はもちろん「アホなフォントに切り替える命令」を想定している。plain TeX の場合、例えば、「\font\AhoFont=cmfi10 scaled \magstep2
」のように定義されたトークン \AhoFont は展開不能だから問題の前提に適っている。これに対して、LaTeX のフォント命令は TeX の(展開可能な)マクロとして実現されるので、問題の前提に合致するフォント切替命令 \AhoFont
を用意するのは難しい。ただし、問題の仕様を満たす \NabeAzzX
を LaTeX *1で実装した場合、LaTeX の「protect(保護)」の機構を利用して次のようなことができるはずである。
\AhoFont
を protect された命令として定義する:*2\DeclareRobustCommand*\AhoFont{\usefont{OT1}{cmfr}{m}{it}\Large}
\typeout{\NabeAzzX{40}}
を実行すると、問題文中で述べた「1 2 {\AhoFont 3} ... 40
」が端末に表示される。((なお、\edef
で試したい場合は、代わりに \protected@edef
という内部命令を用いる必要がある:\protected@edef\result{\NabeAzzX{40}}
))\AhoFont
の定義をどうするかは問題の一部ではないので、例えば「\AhoFont
は \relax
に等置(\let
)されていると思っても良い。)
なお補足であるが、命令(マクロ)を「脆弱」でなくす(「頑強(robust)」にする)のに、必ずしも「完全展開可能」にしなくてもよく、例えば先に述べた LaTeX の protect を使うと、(LaTeX 上では)頑強になる。*3じゃあ何故に完全展開可能性を求めるかというと…もちろんそれが挑戦的で面白いからである。でも、まだ「普通のナベアツ」を終えていない人はさっさとそちらを済ませてからにしよう。