如何避免在组/环境中重置宏定义

如何避免在组/环境中重置宏定义

\pgPtList问题来了:为什么下面的代码会在组结束时重置控制序列的含义?

\documentclass[12pt]{article}

\begin{document}

\begingroup
    \gdef\pgPtList{}
    \edef\pgPtList{8}
    pgPtList is: \pgPtList
    
    \edef\pgPtList{8, 5}
    pgPtList is: \pgPtList
\endgroup

Empty environment has ended.

pgPtList is: \pgPtList

\end{document}

以下是它产生的输出:

pgPtList is: 8
pgPtList is: 8, 5
Empty environment has ended.
pgPtList is:

我目前的理解是,这与团体的工作方式有关,因此可能的后续问题是:我如何重新定义控制序列,使得团体结束后更改仍然保持不变?

以下是更广泛的背景:我正在尝试排版考试并跟踪每页上的分数,并且我不断更新\pgPtList以跟踪每页上的分数。在每次考试中,\pgPtList它都充当另一个创建分数表的命令的默认参数。

每个页面上的点都在一个环境中更新,这就是 reprex 中存在和的enumerate原因。理想情况下,我希望能够在此环境中更新变量,即使点表命令将在此环境之外调用。\begingroup\endgroup\pgPtList

我主要感到困惑的是\edef\gdef。我天真的理解是这些命令旨在使生成的控制序列在当前组之外可访问,但我从上面的代码中获得的输出表明正在发生其他事情。

答案1

  • \def\macroname<argument specification>{definition}是一个局部的、标准的定义;
  • \edef\macroname<argument specification>{definition}是局部的、扩展的定义,即definition在分配之前扩展\macroname
  • \gdef\macroname<argument specification>{definition}是一个全球性的、标准的定义;
  • \xdef\macroname<argument specification>{definition}是一个全球性的、扩展的定义。

就你的情况而言,初始定义\gdef\pgPtList{} 本地组存活。如果没有,则使用\pgPtListafter\endgroup会导致错误。

但是,的所有后续(重新)定义\pgPtList都是明确局部的,因此这些更改不会保留下来\endgroup,并且的含义\pgPtList将恢复为最初的空定义。

下面的例子可能会有帮助:

\documentclass[12pt]{article}

\begin{document}

\newcounter{tweak}
\setcounter{tweak}{0}
\def\rstatement{Redefinition \thetweak.}

\begingroup
  \gdef\pgPtList{Initial, global definition.}
  pgPtList is: \pgPtList
  
  \edef\pgPtList{\rstatement}
  pgPtList is: \pgPtList ; \stepcounter{tweak}\pgPtList
  
  \def\pgPtList{\rstatement}
  pgPtList is: \pgPtList ; \stepcounter{tweak}\pgPtList
\endgroup

Environment has ended.

pgPtList is: \pgPtList

\begingroup
  \xdef\pgPtList{\rstatement}
  pgPtList is: \pgPtList ; \stepcounter{tweak}\pgPtList
\endgroup

Environment has ended.

pgPtList is: \pgPtList

\begingroup
  \gdef\pgPtList{\rstatement}
  pgPtList is: \pgPtList ; \stepcounter{tweak}\pgPtList
\endgroup

Environment has ended.

pgPtList is: \pgPtList

\end{document}

输出说明本地/全局和扩展/标准宏定义

注意,\def确保在使用宏时\gdef使用\pgPtList计数器的值,这可能不是定义时的值。tweak\pgPtList

相反,\edef确保\xdef使用定义时\pgfPtList的计数器值,即使该值在此期间已经发生变化。tweak

另一方面,\def\edef都是局部定义。当前组结束时,它们的效果也随之结束。

相反,\gdef\xdef是全局的。它们一直有效,除非并且直到某个后续的定义\pgfPtList取代它们,而不管分组如何。

相关内容