\foo 1 2 {}
得到的是 *1, 2 *
,而不是 *1,2*
。
TeX 宏的参数有两种,一种是没有分隔符的参数(或定界符,undelimited parameter),另一种是有分隔符的参数(delimited parameter)。参数的分隔符就是两个参数之间的记号,是标记参数结束的一些符号。
TeX 在开始读取 undelimited parameter 时,会忽略空格,之后如果发现第一个记号是 begin-group character,则认为这个参数是由一对括号包裹(可以认为 {
标记参数的开始位置,}
标记结束位置,它们不会在最终的参数里出现),否则这个参数就是遇到的第一个非空格记号。
读取 delimited parameter 时,不会忽略空格,这个参数由指定的定界符来标记结束的位置(定界符必须与定义时的完全匹配),并且 {}
需要正确嵌套,并且如果结果是一对正确嵌套的组,则最外层的括号不会出现在实参中。在这两种情况中,{
可以是任意 catcode 为 1 的字符(即 begin-group character),}
可以是任意 catcode 为 2 的字符(即 end-group character)。
macro parameter(catcode=6 的字符或被 let 为这些字符的控制序列,一般是 #
) + begin-group character 可以看成是一个特殊的定界符,只能放在最末尾。在匹配时,begin-group character 必须和定义时使用的字符完全一致。
如假定 [
和 {
的 catcode 都为 1,则 \def\foo#1#[...}
在使用时也必须是 \foo aaa[...
,不能是 \foo aaa{...
。
了解这些之后,答案就很清楚了。\def\foo#1#2#{...}
,第一个参数是 undelimited parameter,第二个参数由 {
定界,#1
是 1
,#2
分别是 2
和空。
需要注意的是,TeX 在读取一个控制词(如 \a
、\foo
是控制词,\;
是控制符,它们都是控制序列)会忽略它后面的空格,所以 \foo␣␣
等于 \foo␣
等于 \foo
。如前所述,macro parameter 可以是字符,也可以是控制序列,如
\let\pp#
\def\foo#1\pp2{\pp1,#2}
\def\foo#1#2{#1,#2}
两种完全一致。
空格只比较 catcode,不比较 charcode,TeX 在读取输入文本时,所有的 catcode=10 的字符都会变成 charcode=32, catcode=10 的记号。
更详细的内容可以参考 The TeXBook 第 20 章。
问 用形如\def\foo#1#2#{*#1,#2*}这样的代码定义宏时,如何理解参数检索?