在 TeX 中,分组和定义宏()使用相同的字符(即{
和) 。我认为这是因为可以从上下文中区分哪个是哪个。}
\def{...}
因此,有时{
和}
相当于\begingroup
和\endgroup
,有时则不然。但事实证明,花括号还有另一种使用方式。
考虑练习 17.16 的答案电子书:
\def\sqr#1#2{{\vcenter{\vbox{\hrule height.#2pt
\hbox{\vrule width.#2pt height#1pt \kern#1pt
\vrule width.#2pt}
\hrule height.#2pt}}}}
\def\square{\mathchoice\sqr34\sqr34\sqr{2.1}3\sqr{1.5}3}
我们可以删除一层外括号\def\sqr
并直接使用它们,\def\square
如下所示:
\def\square{\mathchoice{\sqr34}{\sqr34}{\sqr{2.1}3}{\sqr{1.5}3}}
那么,括号在什么情况下使用\mathcoice
?它们不用于创建块结构(因为在这里我们不能将{
和替换}
为\begingroup
和),并且这些括号在这里不定义宏。顺便问一下,为什么这些括号对于(不是由单个标记返回的)\endgroup
是必要的?\mathchoice
\vbox
\sqrXY
另外,在什么意义{
上使用\uppercase\expandafter{\romannumeral\year}
:为什么这里的{
and不能被and}
代替?\begingroup
\endgroup
如何区分每次出现的{
或}
使用的意义?例如,如果我们输入 ,{12}
则意味着 TeX 看到 token 12
,或者 TeX 执行\begingroup 12 \endgroup
?如果后者为真,那么作为{12}
参数传递给的外部函数如何获取12
?是\begingroup
...之间的最后一个标记由或使用其他机制\endgroup
返回吗?\endgroup
编辑:就此而言,为什么我们需要\mathchoice...
在练习 17.15 中的以下代码中使用花括号?(即,为什么没有它们就无法工作?)
\def\puzzle{{\mathchoice{D}{T}{S}{SS}}}
$$\puzzle{\puzzle\over\puzzle^{\puzzle^\puzzle}}$$
与以下内容进行比较,其中\alpha
使用时没有额外的括号:
$$\alpha{\alpha\over\alpha^{\alpha^\alpha}}$$
还请注意,在练习 17.16 的答案中,Knuth 没有在 周围加括号\mathchoice...
。为什么?
\def\sqr#1#2{{\vcenter{\vbox{\hrule height.#2pt
\hbox{\vrule width.#2pt height#1pt \kern#1pt
\vrule width.#2pt}
\hrule height.#2pt}}}}
\def\square{\mathchoice\sqr34\sqr34\sqr{2.1}3\sqr{1.5}3}
答案1
根据语法规则,应该跟在<general text>
后面的原语具有非常特殊的行为:它们扩展下一个标记(如果可扩展),以便找到符合条件的标记<filler>
,并最终找到界定 的左括号<balanced text>
。更准确地说,只要语法规则允许(扩展后,是任意数量的 和 空格标记<filler>
的序列),就会发生这种情况。\relax
这样的括号甚至可以是隐式的。因此,如果你这样做
\def\foo{{abc}}
然后\uppercase\foo
会产生ABC
。对于和\mathchoice
,情况类似。语法规则说(TeXbook,第 292 页)_
^
\mathchoice<filler>{<math mode material>}<filler>{<math mode material>}<filler>{<math mode material>}<filler>{<math mode material>}
这意味着完全相同的事情:为了找到<filler>
,TeX 会进行扩展。
因此,如果\sqr
按照所示方式定义,则\mathchoice
其何时工作,它会扩展\sqr
,从而查找其参数并被替换文本替换;由于括号是替换文本的一部分,\mathchoice
“看到”它。
同样的情况\uppercase\expandafter{\romannumeral\year}
:\expandafter
得到扩展。括号界定了<general text>
,因此它们不构成一个组。
语法规则会准确说明何时由于 而进入新的分组级别{
。例如,这种情况发生在框中;在这些情况下,左括号和右括号都可以是隐式的。在 的情况下,<general text>
右括号必须是显式的,因为语法规则为 (p. 276)
<general text> → <filler>{<balanced text><right brace>
切勿将由{
和分隔的组与由和}
分隔的组相混淆。\begingroup
\endgroup
当 TeX 看到{12}
并且没有根据某些语法规则寻找左括号时,它会打开一个“简单组”,执行它找到的标记,并在找到匹配项后}
关闭该组;\begingroup12\endgroup
可以绝不被解释为<general text>
,因为它缺少{
。TeX 打开一个“半单组”,执行标记,并在找到匹配项后\endgroup
关闭该组。
答案2
括号{}
(更准确地说是带有 catcode 1 和 2 的字符)根据上下文具有各种含义。
(1)单独使用时,它们用于开始和结束组。此外,在数学模式下,它们会创建新的 Ord 原子。
(2)它们是宏的参数分隔符(并且它们被从参数的边界中移除)。例如\macro{parameter}
。
(3)当使用 TeX 基元时,它们是语法规则的一部分(例如在\def{body of macro}
或 在\message{message text}
或中) \mathchoice{A}{B}{C}{D}
。
嵌套{}
必须始终匹配,无论其实际含义如何。由于 TeXbook 中描述的语法,某些原语可能存在此规则的特殊例外:\message\bgroup Hello}
或\hbox {text\egroup
。