获取 \expandafter\ 时出现问题\endgroup 按预期工作

获取 \expandafter\ 时出现问题\endgroup 按预期工作

我有一个场景,我正在测试一个组内的条件,然后触发输入相应的外部文件。问题是外部文件可能包含我以后需要的控制序列。我试图确保扩展将在关闭组后发生,如下例所示。(我省略了测试条件,因为这个例子仍然重复了我的错误。)

\begin{filecontents}{anotherfile}
\def\aemoon{This is the moon}
This is my other file.
\end{filecontents}

\documentclass{article}

\begin{document}

Testing

\begingroup
  \def\helloworld{\input{anotherfile}}
  \expandafter\helloworld
\endgroup

\aemoon

\end{document}

但这会导致错误

! Undefined control sequence.
l.17 \aemoon

下面的情况也一样,不需要输入外部文件

\documentclass{article}
\begin{document}

Testing

\begingroup
  \def\helloworld{\newcommand\aemoon{this is the moon}}
  \expandafter\helloworld
\endgroup

\aemoon

\end{document}

在任一例子中,我都期望该命令\aemoon由于 而在组之外定义\expandafter。(由于该组尚未定义,\aftergroup因此显然不起作用。)\helloworld

回想一下我最初输入另一个文件的情况,我知道我可以写类似的东西

\begin{filecontents}{anotherfile}
\def\aemoon{This is the moon}
This is my other file.
\end{filecontents}

\documentclass{article}

\begin{document}

Testing

\begingroup
  \gdef\helloworld{\input{anotherfile}}
\endgroup
\helloworld

\aemoon

\end{document}

所以,我确实有解决办法。但我想知道为什么前两个例子不起作用,因为我的理解是扩展应该在组外进行,但是...

那么,这里发生了什么事?

答案1

你应该说:

\begingroup
  \def\helloworld{\newcommand\aemoon{this is the moon}}
  \expandafter
\endgroup\helloworld

这里的想法是,在 TeX 看到 之前,\expandafter会导致\helloworld被扩展\endgroup,因此首先\helloworld被扩展,然后 TeX 看到\endgroup\newcommand\aemoon{this is the moon}。然后它评估\endgroup\helloworld超出范围,然后它评估\newcommand并被\aemoon定义。

您可能将这种情况与条件语句中有一个带参数的命令的情况相混淆,并且您不希望它使用\fi\else和 false 子句作为其参数,因此您说:\ifsomething \expandafter\somecommand\fi。由于\else和是完全可扩展的,并且在扩展时会删除自身(在false 子句\fi的情况下),这解决了该问题。\else

问题在于\expandafter\helloworld\endgroup\endgroup不可扩展的,所以结果是\expandafter扩展了\endgroup,这根本不会改变它 --\endgroup就像这里的 一样}。那么 TeX 看到的就是\mycommand\endgroup,这并不符合你的要求。

粗略地说,TeX 有两个求值阶段——扩展阶段,它接受宏并反复扩展它们;求值阶段,它接受不可扩展的基元(字符或命令,如\bgroup\relax\def\show)并求值它们。\expandafter仅与扩展阶段交互。TeX 的许多非直观行为都源于这种扩展求值区别。

但是,即使\expandafter\helloworld\egroup的行为确实如您所期望的那样,它也是错误的,因为这与说 相同\egroup\helloworld,这会导致错误,因为 的定义\helloworld超出了范围。

答案2

\endgroup不可扩展,这使得

\begingroup
  \def\helloworld{\newcommand\aemoon{this is the moon}}
  \expandafter\helloworld
\endgroup

相当于

\begingroup
  \def\helloworld{\newcommand\aemoon{this is the moon}}
  \helloworld
\endgroup

因此,\helloworld被定义、执行,然后组中所有未定义、执行的内容\global将不复存在。这包括\aemoon。您可以考虑另一种选择

\begingroup
  \def\helloworld{\endgroup\newcommand\aemoon{this is the moon}}
  \helloworld

\helloworld团体的尽头隐含地\aemoon仍保持定义。

答案3

   \expandafter\helloworld\endgroup

适用\expandafter\endgroup这不是错误,但它不执行任何操作,因为\endgroup它不可扩展,所以它相当于

  \helloworld\endgroup

因此, \helloworld在团体内部采取行动是预期的行为。

相关内容