测试 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 开始解释输入之前。