お待ちかねの(誰が?) TeX パズル。
次のそれぞれのトークン列について、先頭から「グルー値」を 1 つ読んだ場合、どこまでが「グルー値を表す文字列」と解釈されるか。言い換えると、これらの前に\hskip
を置いた場合、どこまでのトークン列が「その引数として読み込まれる」ことになるか。ただし、〈~
〉は空白トークン(カテゴリコード 10)を表すものとする(あるいは、アクティブな〈~
〉に対して\def~{ }
の定義がされていると考えてもよい)。また、数字や英字は通常のカテゴリコードをもつとする。
1cm~plus~~1cm~~x
1cm~minus~1cm~~x
1cm~plus~~1fil~~x
1cm~minus~1fil~~x
答えを述べる前に、「実際に確認する方法」を説明しておく。例えば次のようにすればよい。
\catcode`\~=13 \def~{ } % <~>の定義
\def\check#1\nil{\message{[#1]}}
\afterassignment\check\skip0=1cm~plus~~1cm~~x\nil
結果は以下のようになる。
1cm~plus~~1cm~~x
1cm~minus~1cm~~x
1cm~plus~~1fil~~x
1cm~minus~1fil~~x
何故そうなるかは、グルー値文字列の書式の完全な形を考えれば想像がつく。
1☆cm☆plus☆2☆cm☆minus☆3☆cm※
ここで各要素(キーワードや数字列)の間(☆の位置)には任意個の空白トークンを挟むことができる。そして、整数文字列と同じく、末尾(※の位置)には終結のために 1 個の空白トークンが置ける。これを基に考えると、「plus 1cm
」の後ではまだ途中(後ろに minus
があるかも知れない)なので、続く空白を全て読み捨てた(x
が出現した時点で、その直前で終結させた)のに対し、「minus 1pt
」の後では、もう既に全ての要素を読み終わっているので、「終結のための 1 個の空白」だけを読み捨てたということになる。
この説明では一番最後の「minus 1fil
」の動作が明らかに辻褄が合わないように見える。しかし、実はそうではないのである。これは次の例を見れば解る。
1cm~plus~~1fil~~l~~x
1cm~minus~1fil~~l~~x
この場合、グルー値文字列になる部分は以下の通り。
1cm~plus~~1fil~~l~~x
1cm~minus~1fil~~l~~x
要するに、TeX では「fill
」は 1 つのキーワードではなく、「fil
」「l
」の 2 つのキーワードの列なのである。従って、「fil~~l
」でも有効となり、また「minus 1fill
」まで読んでもまだ途中(先に「l
」があるかも知れない)だから結果的に全ての空白が読まれることになる。((「1filll
」(これより高い無限長はない)まで読んでもなお次の「l
」はキーワードとして読まれて、そこで「Illegal unit of measure (replaced by filll)」のエラーになる。このエラーを見かけたら、是非とも「h」でヘルプを出してみよう。))
ここで話は終わりではない。実は、LuaTeX では結果が異なるのである。
1cm~plus~~1cm~~x
1cm~minus~1cm~~x
1cm~plus~~1fil~~x
1cm~minus~1fil~~x
1cm~plus~~1fil~~l~~x
1cm~minus~1fil~~l~~x
何故この結果になるかは、「cm
」と「fil
」の扱いが同じであることに気づけば解るであろう。つまり、LuaTeX では「fill
」を複数のキーワードの列ではなく単一のキーワードとして扱っているのである。正確に言うと、LuaTeX では、「fi
」「fil
」「fill
」「filll
」が別個のキーワードで「l
」というキーワードは存在しない。*1ゆえに「fil l
」では fil
が単位となり、次の l
を見てその前で終結することになる。
*1:なお、「fi」は「fil」より低位の無限長である。Omega で導入され、LuaTeX にも引き継がれている。