我知道这个回复
这说明这\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
有多种方法可以为控制序列标记赋予含义:
- 宏(用
\def
、\edef
或定义\gdef
)\xdef
; - 原始的;
- 一个
\countdef
、、、、、、或令牌;\dimendef
\skipdef
\muskipdef
\toksdef
\chardef
\mathchardef
- 字体选择器(用 定义
\font
); - 用 定义的标记
\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