Knuth 的 TeXbook 练习 5.6 内容如下:
如果您认为您理解了局部和全局定义,请进行一个小测试以确保:假设
\c
代表\count1=
,\g
代表\global\count1=
,\s
代表\showthe\count1
。将显示哪些值?{\c1\s\g2{\s\c3\s\g4\s\c5\s}\s\c6\s}\s
当我尝试在脑海中遵循这一点并输入“扩展”形式时,我想到了:
{\count1=1\showthe\count1\global\count1=2{\showthe\count1\count1=3\showthe\count1\global\count1=4\showthe\count1\count1=5\showthe\count1}\showthe\count1\count1=6\showthe\count1}\showthe\count1
但这给了我一个错误。以下是整个练习的更易读的版本:
{% outer block
\count1=1%
\showthe\count1%
\global\count1=2%
{% inner block
\showthe\count1%
\count1=3%
\showthe\count1%
\global\count1=4%
\showthe\count1%
\count1=5%
\showthe\count1%
}%
\showthe\count1%
\count1=6%
\showthe\count1%
}%
\showthe\count1
Prediction:
1 2 3 4 5 4 6 4
\end
错误是:
$ tex chapter5.tex
This is TeX, Version 3.14159265 (TeX Live 2017/Debian) (preloaded format=tex)
(./chapter5.tex
> 1.
<to be read again>
\global
l.4 \global
\count1=2%
?
注意:我不知道我是否在尾随方面做得过头了%
,但谨慎一点总是好的 ;)
这是怎么回事?或者也许这就是 TeX 阻止我隐藏先前分配的当地的通过分配具有相同名称的全局变量来改变变量?
顺便说一句:我的猜测是 1 2 3 4 5 4 6 4,但我无法验证这个结果。我知道这是评分二“危险弯道”,这是我第一次阅读 TeXbook,但我发现它很有趣,所以决定尝试一下。
答案1
该命令\showthe
将使 TeX 停止并在控制台上显示值。它使用与显示错误消息相同的机制,这可能是您想到要制作一个的原因。
该代码根本不会产生任何输出。
打印数字的版本:
\def\c{\count1=}
\def\g{\global\count1=}
\def\s{\relax\the\count1\space\space}
{\c1\s\g2{\s\c3\s\g4\s\c5\s}\s\c6\s}\s
\bye
进一步练习:为什么\relax
和\space\space
?
也\relax
可以是\space
;也\space\space
可以是\relax\space
。如果我们扩展定义,我们首先得到
\count1=1\relax\the\count1\space\space
或者
\count1=1\relax\the\count1\relax\space
TeX 总是会在常数(使用宏扩展)后寻找空格,然后忽略它。常数的终止非常重要。实际上,首先不是,因为后面跟着的是\global
不能解释为数字的那个。但是\g4\s\c5
,如果是,则没有,\relax
我们会得到
\global\count1=4\the\count1
这将分配\count1
一个不同的值,即 43,因为 TeX 将继续扩展\the
。
重复输入\space
意味着\s
在数字之间打印一个空格;第一个\space
将被忽略,第二个输出一个空格。使用\relax
也会结束扩展,因为\relax
不能将其解释为数字。