是否可以暂时使未定义的 \csname 控制序列不会悄悄地扩展到 \relax?

是否可以暂时使未定义的 \csname 控制序列不会悄悄地扩展到 \relax?

语境

请考虑以下情况。

\documentclass{minimal}
\makeatletter
\expandafter\def\csname/test\endcsname{%
  \foo{bar}}
\def\mymacro#1{%
  % Note the / *after* #1
  \expandafter\expandafter\expandafter\mymacro@i\csname/#1/\endcsname}
\def\mymacro@i\foo#1{%
  \def\temp{#1}%
  \show\temp}
\mymacro{test}
% Error: Use of \mymacro@i doesn't match its definition.
\begin{document}
\end{document}

我在之前\mymacro添加的定义中犯了一个拼写错误。显示的错误让我相信这三个错误扩展了,但是/\endcsname/test\expandafter我错了。由于/test/未定义,它会默默扩展为\relax,并且是的,因为我用而不是来喂它,TeX所以说是正确的。Use of \mymacro@i doesn't match its definition\relax\foo

问题

这种\csname定义的控制序列(即在\relax未定义时扩展)的行为确实很方便,但有时我想停用它并可能发出错误Undefined control sequence。 可能吗?

答案1

您无法改变的行为\csname,但您可以使用 e-TeX\ifcsname发出错误:

\csname
  \ifcsname#1\endcsname
  \else
    \expandafter\UndefinedName
  \fi
  #1%
\endcsname

其中\UndefinedName是故意不定义的。TeX 随后会发出一个错误,抱怨Undefined control sequence,然后是#1(这才是您真正想要抱怨的)。

(与 不同\@ifundefined\ifcsname是可扩展的并且不会添加到哈希表中。)

答案2

您可以检查命令是否存在并自行调用错误。

\@ifundefined{/#1/}{%
  \GenericError{}{%
    Command /#1/ undefined!
  }{%
    See the definition of \protect\mymacro!
  }
}{}%

\@ifundefined宏使用,\csname因此它将宏定义为\relax。我不认为这是一个问题(无论如何我们都会调用错误),但您可以用 包围代码以\begingroup ... \endgroup使定义成为本地的。

答案3

问题中写道:

\csname 定义控制序列的这种行为(即未定义时扩展为 \relax)确实很方便,但有时我想停用它,并可能发出未定义的控制序列错误。可能吗?

\csname用于从标记序列中获取控制序列标记,这些标记在扩展的某个阶段会产生一个字符标记序列,代表所讨论的控制序列标记的名称。如果所讨论的控制序列标记在应用时未定义\csname,则会为其分配 -primitive 的含义\relax。(即使 -parameter\globaldefs具有正值,该分配也仅限于当前范围。)

因此,在这种情况下,\csname-定义的控制序列不会扩展为。它根本不会扩展,因为它不可扩展,因为它具有与不可扩展标记的-原\relax语相同的含义。\relax

用 来“命中”不可扩展标记\expandafter不会影响这些标记。\expandafter本身是可扩展的。所有扩展都在 TeX 的口中进行。因此处理\expandafter将在 TeX 的口中进行。不可扩展标记不受此影响。它们到达 TeX 的胃中。

\mymacro@i预计由控制字标记界定,\foo而第一个-chain 来自“命中”\expandafter的扩展,这反过来又提供不可扩展的控制字标记,其含义等于不可扩展的 -primitive 的含义。当被第二个 -chain “命中”时,该不可扩展的控制字标记不受影响。\mymacro{test}\csname\/test/\relax\expandafter

顺便说一句 1:对于带分隔符的参数,TeX 通常在收集参数时会删除参数分隔符。因此,在收集参数时,参数分隔符的含义并不重要。您甚至可以愉快地使用未定义的符作为参数分隔符。

顺便说一句 2:不要使用 minimal 类来制作最小示例。请改用 article 类。minimal
类是由 LaTeX2e 包的开发人员编写的,用于测试 LaTeX2e 包的类加载机制。

相关内容