如果使用 \csname...\endcsname 对命名控制序列,则 \ifx 会以不同的方式处理该控制序列

如果使用 \csname...\endcsname 对命名控制序列,则 \ifx 会以不同的方式处理该控制序列

这两种表达方式

\a

\csname a\endcsname

应该是等价的吗?

然而,下面的纯 TeX 手稿

\ifx\a\relax yes\else no\fi\bye

输出

而所谓的等价

\expandafter\ifx\csname a\endcsname\relax yes\else no\fi\bye

输出

是的

答案1

它们相当于\ifx

\ifx\a\relax yes\else no\fi



\expandafter\ifx\csname a\endcsname\relax yes\else no\fi


\ifx\a\relax yes\else no\fi

\bye

生产

否 是 是

\a如果已定义则为是(并且 csname 已将其定义为\relax),否则为否。

答案2

这两个结构不应该是等同的。

TeXbook 中的练习 7.7(第 40 页)说

\csname第一次使用来定义控制序列时,该控制序列将被视为等同于,\relax直到被重新定义为止。

如果你编译

\tracingassigns=1
\expandafter\def\csname a\endcsname{whatever}

使用支持 e-TeX 的引擎(pdftex例如),日志文件将包含

{changing \a=undefined}
{into \a=\relax}
{changing \a=\relax}
{into \a=macro:->whatever}

这更好地解释了练习中的措辞。

接下来我们阅读第 213 页

  • \csname...\endcsname。TeX 扩展时\csname 会读取匹配的\endcsname,并在进行时扩展标记;扩展完成后,只应保留字符标记。然后,整个\csname...\endcsname文本的“扩展”将是一个控制序列标记,其定义为类似于\relax其含义当前未定义。

这意味着

\expandafter\ifx\csname a\endcsname\relax

将返回 true ,除非\a在测试之前定义为某些含义不明确的事物\relax

相反,如果\a没有定义,

\begingroup\expandafter\endgroup
\expandafter\ifx\csname a\endcsname\relax

将返回 false,因为\endgroup是在条件测试之前执行的,但在\a从 构建之后\csname a\endcsname;组的末尾将删除先前分配给 的含义\a。但是,此构造不可扩展:例如,

\edef\x{\begingroup\expandafter\endgroup\expandafter\ifx\csname a\endcsname\relax true\else false\fi}

\x扩展到\begingroup\endgroup true,因为\begingroup\endgroup在期间未执行\edef

\ifcsname这就是将 添加到 e-TeX的主要原因:当\ifcsname...\endcsname执行 时,构造的标记不会等同于\relax

相关内容