
次のようなプレーンな Tex コードがあります。
\def\xx{ABC}
\def\temp #1 {\def\tempii{#1}}
\temp\xx a b c
\tempii\tempii
次のような出力が表示されるはずです。
a b c ABCABC
しかし、私は実際にこれを見ます:
b c ABCaABCa
\tempii の定義に「a」が組み込まれているのはなぜですか?
答え1
なぜそうなるのかはまだ考えていますが、この改訂版(を採用\xx
)により、希望どおりの結果が得られます。
答えは、 の使用法では\temp\xx a b c
、 の後のスペースは\xx
TeX パーサーの視点から見ると、スペースではなく、単にマクロ名 の終わりを示すだけである、ということだと思います\xx
。たとえば、 だけを\xx A
1 行に記述すると、スペースなしで と印刷されますABCA
。したがって、パーサーは、 に接続されている末尾の "A" を取り込み、 に接続します。 は、 の後に続く文字ではなく、スペースが区切り文字であることをパーサーに伝える方法として\xx
使用できます。\temp\xx{} a b c
\xx
\documentclass{article}
\begin{document}
\def\xx{ABC}
\def\temp #1 {\def\tempii{#1}}
\temp{\xx} a b c
\tempii\tempii
\end{document}
答え2
わかりやすくするために、スペース トークンは で示します。•
これは、説明において非常に重要なためです。次のコード サンプル内のスペースは無視してください。
のパラメータテキスト\temp
は
#1•
置換テキストは
\def\tempii{#1}
あなたの呼び出し\temp
は
\temp\xx a•b•c•\tempii\tempii
\xx
マクロを区切るためのスペースが後に続くことに注意してください。ないスペーストークン: TeXは常に制御文字の後のスペースを無視するので、これは何の意味もありません。言葉(制御しないシンボル)。その後のスペースは、c
コードの行末から来ます。
続くトークンは\temp
(拡張なしで)パラメータテキストと一致するものを探すためにスキャンされます。引数はスペースで区切られているため、#1
終了し\xx a
、入力ストリームの次の状態は次のようになります。
\def\tempii{\xx a}b•c•\tempii\tempii
ここで、TeX は定義を実行し、それを入力ストリームから削除します。
b•c•\tempii\tempii
そして、その部分はb•c•
タイプセットの段階に渡されます。 の2つのコピーを展開した後\tempii
、これは次のように入力したのと同等です。
b•c•\xx a\xx a
または
b•c•ABCaABCa
まさにそれがあなたが得たものです。
\?
最後の2行の代わりに使用した場合、\xx
次のように変換されます。
\temp\?•a•b•c•\tempii\tempii
\?
は制御記号であり、TeXはその後のスペースを無視しない。この場合、結果は次のようになる。
a•b•c•ABCABC
ご了承ください
\expandafter\temp\xx a•b•c
\tempii\tempii
同じ結果になる。なぜなら、\expandafter
TeXのアクションの後に、
\temp ABCa•b•c
(もちろん、スペースについては前と同じ規則に従います)。の\?
代わりにを使用すると、同じ結果が得られます。\xx
\expandafter\temp\expandafter\xx\space a•b•c
なぜなら、TeXは次のように表示されるからです
\temp\xx•a•b•c
実際、スペースはトークン化プロセス中にのみ制御ワードの後に無視されます。