这两种表达方式
\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
。