マクロツイーター

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

整数を読み飛ばす

TeX パズル」の第 2 段。

いま、日本語が通る「ナントカTeX」があったとして、それで pTeX の動作をエミュレートしたい、という状況を想定する。その「ナントカTeX」は日本語を含む TeX 文書を処理することができるが、残念ながら \ybaselineshift(寸法パラメタ)や \prebreakpenalty(非負整数の添字をとる整数パラメタ)に直接対応するプリミティブは持っていないとする。そこで、これらのパラメタに対してダミーのレジスタで偽装して、「機能はしないがそのパラメタの読み書きは可能」なようにすることを考えたとする。*1どう実現すればよいだろうか。

ybaselineshift の方は話が簡単である。単にそれ自身をダミーレジスタとして定義すればよい。


\newdimen\ybaselineshift

\prebreakpenalty の方が難しいが、これについては、\newcount\xx@dummy@count として整数レジスタを 1 つだけ確保し、「\prebreakpenalty〈非負整数〉」の形の記述は全部このダミーの \xx@dummy@count とみなされるようにすればいいだろう。

……という長い状況説明が終わって、さて問題である。

\prebreakpenalty〈非負整数n〉 が n の値に関わりなく \xx@dummy@count に展開されるようにマクロ \prebreakpenalty を実装せよ。(必要ならば追加のレジスタを確保してもよい。)

要するに、「整数を 1 つ読み飛ばしたい」ということである。ここで「展開」でなければならない理由は、読み書き可能なパラメタの使われ方を見れば判ると思う。


1. \count255=\prebreakpenalty20
2. \prebreakpenalty20=50
3. \edef\foo{\the\prebreakpenalty20}

例えば単純に以下のようにすると、1. はよいが 2. は失敗する。


\newcount\xx@dummy@count@a
\def\prebreakpenalty{\xx@dummy@count@a \xx@dummy@count@a=}

少し凝って次のようにすると 2. はよいが今度は 1. が失敗する。


\newcount\xx@dummy@count@a
\def\prebreakpenalty{\afterassignment\xx@dummy@count@a \xx@dummy@count@a=}

そもそもこのような代入を伴う方法では 3. のようなケースには絶対対応できない。ゆえに、前述の目的ではどうしても展開だけで処理する必要があるのである。あと、注意すべきなのは、他のプログラミング言語と同様、TeX で整数を表す方法は多様にあるということである。


"1CD
`?
\year %(整数パラメタ)
\skip42 %(グルーレジスタ、整数にキャスト)
\count2\expandafter\@car\the\parindent\@nil % TRIP的表記 ;-)

最後の \@car...\@nilLaTeX の内部マクロである。実際には \prebreakpenalty でこんな奇怪な記述が用いられるとは思われないが、今回の出題では、全ての整数の形式に対応する(すなわちこんなのをも相手にしなければいけない)ことを要請する。

*1:問題のための設定なので、このような設計が適切かは措いておく。