例如:latex 代码:
\documentclass{article}
\begin{document}
% test-case 1
% Output: "b"
% Expansion is not allowed, and implicit token doesn't take effect.
\begingroup
\let\implicitToken=b
\uppercase{\implicitToken}
\endgroup
% test-case 2
% Output: "b"
% Expansion is allowed, and implicit token takes effect.
\begingroup
\let\implicitToken=b
\if \implicitToken b
b
\else
B
\fi
\endgroup
% test-case 3
% Compile error: \cq is undefined
% Expansion is not allowed, and implicit token doesn't take effect.
\begingroup
\let\implicitToken\cq
\def\implicitToken{}
\cq
\endgroup
% test-case 4
% Output: "B"
% Expansion is allowed, but implicit token doesn't take effect.
\begingroup
\let\implicitToken=b
\edef\cq{\implicitToken}
\let\implicitToken=B
\cq
\endgroup
\end{document}
以下是我的问题:
如果上下文允许扩展,是否允许隐式标记?
这可能是解释测试用例 1、2、3 的唯一方法。但它无法解释测试用例 4。
如果不允许,什么时候才允许?
我已阅读 TeXByTopic 但找不到确定的结论。
答案1
隐式标记不会扩展其含义,它们是它们的意义。
\let\tokenAlias=b
\tokenAlias
是一个b
。这出现在您的第二个测试中:\tokenAlias
和b
完全等价。
但是,大小写转换是根据相关标记的字符代码进行的。(如注释中所述,\uppercase
也是不可扩展的。)因此,由于它根本没有字符代码,因此\tokenAlias
不会受到影响,它是一个控制序列。\uppercase
让隐式字符标记“自然出现”的唯一方法是迭代输入并对每个输入的含义进行测试,用其含义替换每个隐式标记。
每次进行一个测试(编辑后),在任何情况下都不会发生扩展。因此:
\implicitToken
保持不变,因为它在大写字母表中没有字符代码\implicitToken
是b
,因此比较两者使用\if
是正确的:有不的扩展\implicitToken
。\cq
从未定义,因此\let
和\def
行无效由于没有扩展,所以
\edef
不执行任何操作。相反,我们最终会得到替换文本:因此,其效果取决于使用时的含义。\implicitToken
\cq
\implicitToken
再次注意排版不是扩展上下文:结果取决于执行的令牌。
答案2
让我们逐一分析您的测试。
一个隐式标记(更准确地说是隐式字符标记)是由 定义的符号标记\let<token>=<character>
。
测试 2
% test-case 2
% Output: "b"
% Expansion is enabled, and implicit token takes effect.
\begingroup
\let\implicitToken=b
\if \implicitToken b
b
\else
B
\fi
\endgroup
这将输出“b”,因为隐式标记的行为类似于它被定义为相等的字符在上下文中的\if
或\ifcat
。
测试 3
% test-case 3
% Compile error: \cq is undefined
% Expansion is disabled, and implicit token doesn't take effect.
\begingroup
\let\implicitToken\cq
\def\implicitToken{}
\cq
\endgroup
这比较简单:赋值\def\implicitToken{}
会覆盖\let
。另一方面,\implicitToken
永远不会使用,并且\cq
(undefined) 会引发错误。
测试 4
% test-case 4
% Output: "B"
% Expansion is enabled, but implicit token doesn't take effect.
\begingroup
\let\implicitToken=b
\edef\cq{\implicitToken}
\let\implicitToken=B
\cq
\endgroup
如果你\show\cq
在执行完后添加,\edef
你会看到
> \cq=macro:
->\implicitToken .
并且由于后续的重新定义,输出将包含“B”。
隐式标记是不是可扩展,所以代码
\let\implicitToken=b
\edef\cq{\implicitToken}
和
\let\implicitToken=b
\def\cq{\implicitToken}
\implicitToken
完全等价。TeX 将使用时间扩展中的当前含义\cq
:在您的测试中,它是“B”。
测试 1
% test-case 1
% Output: "b"
% Expansion is disabled, and implicit token doesn't take effect.
\begingroup
\let\implicitToken=b
\uppercase{\implicitToken}
\endgroup
原语\uppercase
检查其参数(没有宏扩展,但这里无关紧要)并转换每个明确的字符标记转换为大写形式(存储在\uccode
向量中)。它没有对隐式标记采取行动。
评论
存在不对称性:使用\let\implicitToken=b
,测试\if\implicitToken b
将返回 true。类似地,\ifcat
将使用定义时当前字符的类别代码;例如
\let\implicitToken=b
\catcode`b=12
\ifcat\implicitToken a%
\message{letter}%
\else
\message{nonletter}%
\fi
letter
将在控制台上打印,而\ifcat ba
会打印nonletter
。
为什么会出现这种不对称?抱歉,只有 Donald Knuth 可以回答。隐式标记的最突出用法是和\bgroup
,\egroup
它们可以在某些(并非所有)上下文中替代{
和。我猜让它们在或}
中进行转换会很烦人。\uppercase
\lowercase
扩张
TeX 中的标记可以是可扩展的,也可以是不可扩展的。后一种标记在单独找到时,会直接传递给执行处理器。这是什么意思?让我们看一个例子。原语\dimen
是不可扩展的。如果 TeX 找到\dimen2=12pt
,它将传递\dimen
给执行处理器;执行提示在输入流中搜索一个<number>
、一个<optional equal>
和一个合适的值(带扩展)。相反,在 中\advance\dimen2 by 2pt
,标记\dimen
被吸收作为 的参数进行\advance
进一步处理。非活动(显式)字符标记是不可扩展的;活动字符可以是或不可以是,这取决于如何定义其含义。
哪些代币是可扩展的?很简单:
- 一些原语,例如条件、
\string
等等\noexpand
; - 宏,即用
\def
、\edef
或定义\gdef
的标记\xdef
; - 标记
\let
等于可扩展标记。
由于您的\implicitToken
不属于上述任何类型,因此无法扩展。