在 \if 构造的“眼中”,活动字符的字符代码是什么?

在 \if 构造的“眼中”,活动字符的字符代码是什么?

根据 TeXbook* 的描述

\if<token1><token2>

构建于第 209 页(重点是我的)

TeX将扩展后面的宏,\if直到找到两个不可扩展的标记。如果任一标记是控制序列,则TeX认为它具有字符代码 256 和类别代码 16,除非该控制序列的当前等价物等于\let非活动字符标记。这样,每个 token 指定一(character code, category code)

如果其中一个或两个不可扩展标记都是活动字符,该怎么办?例如

\catcode`@=13%
\if\noexpand @ ...

在构造体的“眼中”,主动角色的有效角色代码是什么\if


* 第 20 次印刷,Addison-Wesley 1991

答案1

如果你用抑制扩展,\noexpand那么它就像一个命令名称,所以如果它被设置为一个字符,那么它就是一个字符代码,

如果使用 抑制扩展,\string则会\if看到 catcode 12 的非活动标记,其中包含原始字符的字符代码。

\catcode`@=13
\let@=X

\if\noexpand @X yes \else no\fi


\if\noexpand @ \string@ yes \else no\fi


\bye

使

是 否

因为\noexpand这里的测试等于 X,所以它等于\letX,但请注意,如果字符等于\let这里的字符,那么它是不可扩展的,所以\noexpand不需要。

答案2

请务必小心!您的代码是

\catcode`@=13%
\if\noexpand @ ...

第一行以 开头\catcode,因此 TeX 开始进行赋值。它找到数字`@(字母常数),因此赋值给 类别代码@。然后=基本上被忽略,因为它是可选的,现在 TeX 想要看到<number>

<number>它找到了两个数字,但是只有当出现非数字时,对它的求值才会结束,并带有宏扩展。

如果删除%,则行尾会生成一个空格标记,并且这是一个非数字,因此<number>TeX 正在寻找的被确定为13(并且空格标记将被忽略)。

对于%,TeX 发现\if是可扩展的,因此 TeX 会对其进行扩展。 的扩展\if为空,但 TeX 首先会扩展标记,直到找到两个不可扩展的标记,然后对它们进行比较;比较后它将返回 true 或 false。

下一个标记是\noexpand,它本身是可扩展的,因此它被扩展;它的扩展为空,但是下一个标记(无论它是什么)如果是可扩展的控制序列则暂时等同于\relax,如果是活动字符则暂时等同于字符本身,这样就结束了对第一个不可扩展标记的查找。

下一个标记@没有尚未更改其类别代码,因为分配尚未结束。只有在找到下一个不可扩展的标记(在本例中为空格)后,TeX 才会确定它<number>仍在寻找的确实是13,并将继续执行分配。

检查以下代码,其中使用组来限制类别代码的变化,以免破坏以下测试。

\let\at=@

\begingroup
\catcode`@=13%
\if\noexpand @\at \message{true}\else\message{false}\fi
\endgroup

\begingroup
\catcode`@=13%
\if @\at \message{true}\else\message{false}\fi
\endgroup

\begingroup
\catcode`@=13
\if @\at \message{true}\else\message{false}\fi
\endgroup

终端上的输出是

true true
! Undefined control sequence.
l.15 \if @
          \relax \message{true}\else\message{false}\fi

并且只有在第三次测试中才@变为活跃状态,才\if进行测试。

如果第三次测试

\catcode`@=13
\if \noexpand @\at \message{true}\else\message{false}\fi

那么它也会返回 true,因为只会返回没有扩展能力的\noexpand @字符。@

故事的道德启示:常量后总是留一个空格

相关内容