\edef 中 csname/endcsname 的扩展规则

\edef 中 csname/endcsname 的扩展规则

我知道这个回复

为什么 \def 在 \edef 里面会失败?

这说明这\def是不可扩展的,因此随后在 内尝试的定义都会失败\edef

我想了解为什么以下所有内容都能按预期工作:

\edef\x{\expandafter\def\csname y\endcsname{1}\y}
\edef\x{\expandafter\edef\csname y\endcsname{1}\y}
\edef\x{\expandafter\let\csname y\endcsname=1\y}

编辑

以上所有方法单独使用时都可以正常工作。特别是,

\edef\x{\expandafter\def\csname y\endcsname{1}\y}

\x

\edef\x{\expandafter\edef\csname z\endcsname{2}\z}

\x

\edef\x{\expandafter\let\csname w\endcsname=3\w}

\x

将产生

1
2
3

\edef\x{\expandafter\def\csname y\endcsname{1}\y}

\x

\edef\x{\expandafter\edef\csname y\endcsname{2}\y}

\x   % where the error appears.

\edef\x{\expandafter\let\csname y\endcsname=3\y}

\x

产生错误

! Missing control sequence inserted.
<inserted text> 
                \inaccessible 
l.33 \x

答案1

\csname是可扩展的,这意味着它将在 中执行其操作\edef。操作是从它找到的标记构建一个控制序列标记,直到匹配的\endcsname,并在过程中执行完全扩展。

一旦 操作\csname结束,标记将根据上下文进行扩展或不扩展;在 中\edef,只要标记可扩展,它就会扩展。如果标记不可扩展,则\edef只需将其存储在正在构建的替换文本中,然后继续处理下一个标记。

因此问题是:token由什么产生\csname y\endcsname?显然\y,但现在它的可扩展性取决于所\y具有的含义。

有两种情况:

  • \y没有先前的含义(即未定义);

  • \y已被 TeX 所知。

\y有多种方法可以为控制序列标记赋予含义:

  1. 宏(用\def\edef或定义\gdef\xdef
  2. 原始的;
  3. 一个\countdef、、、、、、或令牌;\dimendef\skipdef​​\muskipdef\toksdef\chardef\mathchardef
  4. 字体选择器(用 定义\font);
  5. 用 定义的标记\let

在情况 1 中\y是可扩展的;在情况 2 中,它可能是可扩展的,也可能不是,这取决于原语(例如\if,是可扩展的,\the不是可扩展的)。在情况 3 和 4 中是不可扩展的。在情况 5 中,它从其所属的标记继承了可扩展性(和定义性)。\csname\relax\y\y\let

然而,大的之间的区别

\edef\x{... \y ...}

\edef\x{... \csname y\endcsname ...}

when\y没有先前的含义。当使用 构建标记时\csname,如果它是未知的,TeX 将总是赋予它与相同的含义\relax(这种赋值是局部的)。

考虑你的\edef\x{\expandafter\def\csname y\endcsname{1}\y},它与 相同\edef\x{\def\csname y\endcsname{1}\y}(因为\def不可扩展)。假设\y没有先前的定义,则构建的标记相当于\relax。事实上,如果你添加 ,\show\x你将得到答案

> \x=macro:
->\def \y {1}\y .

现在如果你执行 \x\y将被定义为扩展为 的宏1。接下来的\edef\x{\def\csname y\endcsname{1}\y}将会\show\x打印

> \x=macro:
->\def 1{1}1.

请注意,构建的令牌展开,因为现在\y是一个宏。

仍然不会引发任何错误,因为 TeX 只是存储了定义。但是如果我们尝试\x执行

! Missing control sequence inserted.
<inserted text> 
                \inaccessible 
<to be read again> 
                   1
\x ->\def 1
           {1}1

因为\def 1这是违法的。

您的“工作”示例不会引发错误,因为在执行时\y\z\w是未定义的标记。\edef\x{...}

为了完整性,当您执行\edef\x{... \y ...}并且\y未定义时会发生什么?当然,在执行Undefined control sequence时您会得到一个错误。\edef

相关内容