为什么宏参数中的空格不会被忽略?

为什么宏参数中的空格不会被忽略?

测试 1 打印忽略空间。由此我们得出结论,\s在参数扫描时会忽略空格。测试 2 与测试 1 不同,* 附加在参数列表中。如果在参数扫描时忽略空格,则 #1 应该为空。但测试 2 打印空间。为什么测试 1 和测试 2 不一致?哪一个工作正常?TeXbook 在哪里解释过这个问题?

测试 1:

\def\a{*}
\def\x#1{\expandafter\xx\the#1}
\def\xx#1{\def\next{#1}\ifx\next\space\message{SPACE}\fi\ifx\next\a\message{SPACE IGNORED}\fi}
\newtoks\s \s={ } \x\s*
\bye

测试2:

\def\a{*}
\def\x#1{\expandafter\xx\the#1}
\def\xx#1*{\def\next{#1}\ifx\next\space\message{SPACE}\fi\ifx\next\a\message{SPACE IGNORED}\fi}
\newtoks\s \s={ } \x\s*
\bye

答案1

参见 TeXbook 第 201 页(靠近底部):

在说完‘ \def\row#1#2{...}’之后,您可以在参数之间添加空格(例如‘ \row x n’),因为 TeX 不使用单个空格作为未分隔的参数。

TeX 在寻找未限定的参数时会忽略空格标记,但在寻找限定的参数时则不会。

这是两种情况的巨大差异,我们可以将其统一在一个输入文件中。

\newtoks\s \s={ }

\def\a{*}

\def\x#1{\expandafter\xx\the#1}
\def\xx#1{\def\next{#1}\ifx\next\space\message{SPACE}\fi\ifx\next\a\message{SPACE IGNORED}\fi}

\def\y#1{\expandafter\yy\the#1}
\def\yy#1*{\def\next{#1}\ifx\next\space\message{SPACE}\fi\ifx\next\a\message{SPACE IGNORED}\fi}

\x\s*

\y\s*

\bye

在控制台中我们会看到

SPACE IGNORED SPACE

并且,如上所述,不同之处在于的参数\xx是无界的,而的参数\yy是有界的。

让我们来看一下扩展和分配。 空格标记将表示为

\x\s*
\expandafter\xx\the\s*
\xx•*

在这种情况下,参数\xx*,我们看到最后一行变成

\def\next{*}\ifx\next\space\message{SPACE}\fi\ifx\next\a\message{SPACE IGNORED}\fi

我们正确得到了SPACE IGNORED

在第二种情况下,我们得到

\y\s*
\expandafter\yy\the\s*
\yy•*

并且,根据定义,的参数\yy,使得\next等同于\space

我希望你没有对 TeX 忽略控制字后的空格这一事实感到困惑在标记化过程中:这是一个完全不同的过程,发生在 TeX 开始解释输入之前。

相关内容