解析输入时,类别代码 11(字母)和 12(其他)是不同的(后者不能作为多字符控制序列的一部分出现)。
然而,当它们已经被解析时,它们似乎没有太大的区别。它们都是
- 不可扩展
- 执行时自行排版
\scantokens
在等中使用时转换为相同的东西。
除了使得\ifx
返回为 false(或\ifcat
)并强迫用户使用来\tl_analysis_show:N
弄清楚发生了什么,这有什么实际用途吗?
(此外 - 如果这有任何答案,为什么会这样而不是例如两者都转换为 catcode 12?只是历史遗迹,还是有某种原因使它更有意义?)
答案1
控制序列可以有两种类型:
- 控制符号,或
- 一个控制字。
为了让 TeX 标记一个控制序列,您需要输入转义字符(通常是反斜杠,但任何类别代码 0 的字符都可以);此时 TeX 将按以下方式扫描:
如果后续字符的类别代码不同于 11,则该控制序列为控制符号,其名称由该单个字符组成;
如果以下字符的类别代码为 11,则 TeX 继续扫描,直到找到类别代码不是 11 的字符;控制序列是一个控制字,其名称由在此过程中找到的字符运行组成。
如果是控制符号,扫描将正常恢复;如果是控制字,TeX 将进入“跳过空白”的扫描状态。
我认为类别代码 11 和 12 之间的区别是非常重要的。
在标记化之后,区别变得有些模糊;例如,在连字类别中,代码 11 和 12 被接受用于连字目的以形成一个单词。
另一方面,\lowercase
保留与\uppercase
字符关联的类别代码,如果您想要正确解析可能来自任何地方的内容,那么保留类别代码可能更好。或者不保留,正如示例\ifx
所示。这取决于 Knuth 的决定,并且代码可能非常依赖于它。
答案2
正如我在评论中指出的那样,一旦标记化,标记就会永远带有其 catcode。它是标记身份的固有部分。当 catcode 发生更改时,这将成为一项至关重要的功能,因为它允许在 catcode 更改之前定义的代码按预期运行,即使在 catcode 更改之后执行也是如此。
考虑以下代码:
\documentclass{article}
\begin{document}
\def\z{\Q1}
\def\Q{\textit{Q}}
\expandafter\def\csname Q1\endcsname{\textit{Q1}}
\catcode`1=11
\def\zz{\Q1}
\z
\zz
\end{document}
忽略 catcode 意味着 和 的定义\z
相同\zz
。然而,由于 catcode 的原因,情况并非如此。在 的定义中\z
, 的1
catcode 为 12,而在 的定义中\zz
, 的1
catcode 为 11。
尽管 的 catcode1
已更改为 11,但宏\z
即使在 catcode 更改后执行,其行为仍与定义时一样(其1
catcode 为 12)。
\z
因此和的结果\zz
并不相同:
如果不按这种方式运行,整个 TeX 构造就会崩溃。标记化时有效的 catcode 必须在其使用期间保持有效。(虽然考虑到 catcode 11 和 12,这似乎并不十分清楚,但请考虑 catcode 、\
和{
发生}
更改时的效果——我们依靠预先存在的代码来继承其定义中的 catcode 0、1 和 2,以便正确执行)