\csname 未按预期工作

\csname 未按预期工作

以下代码打印 ==atname==

\def\atname{atname}
\def\xxx{name}
\def\at{at}
==\csname\at\xxx\endcsname==
\bye

但事实并非如此:

\def\@name{atname}
\def\xxx{name}
\def\at{@}
==\csname\at\xxx\endcsname==
\bye

为什么?我怎样才能实现这一点?

答案1

\def\@name{atname}未定义\@name,但\@带有参数 text name。同样在纯 TeX 中, 的默认 catcode 为@12。

\catcode`\@=11
\def\@name{atname}
\def\xxx{name}
\def\at{@}
==\csname\at\xxx\endcsname==
\bye

答案2

控制序列定义由三部分组成:

  1. 控制序列名称;
  2. 参数文本;
  3. 替换文本。

参数文本是控制序列名称和界定替换文本的左括号{1之间的任何内容。它包含参数标记#1... #9,还包括其他标记。

控制序列可以由一个或多个字母的序列组成(在这种情况下,字母是类别代码为 11 的字符),也可以由单身的非字母(任何类别代码)。

但是,控制序列名称可以通过扩展来形成:将使用\csname由标记的完整扩展直至匹配所产生的所有字符标记,而与它们的类别代码无关。\endcsname

在正常设置下,@类别代码为 12,因此

\def\@name{atname}

定义\@,因为单个非字母会结束对控制序列名称的扫描。参数文本是标记列表name,它是必需的\@在使用时遵循。

所以你可以通过以下方式

\catcode`@=11 % make @ a letter
\def\@name{atname}
\catcode`@=12 % go back to the default
\def\xxx{name}
\def\at{@}
==\csname\at\xxx\endcsname==
\bye

或者

\expandafter\def\csname @name\endcsname{atname}
\def\xxx{name}
\def\at{@}
==\csname\at\xxx\endcsname==
\bye

因为\expandafter控制序列名称由扩展组成\csname \def完成其工作。

相关内容