如何避免在群組/環境中重置巨集定義

如何避免在群組/環境中重置巨集定義

\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充當另一個建立分數表的命令的預設參數。

每個頁面上的點都會在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}

輸出說明本地/全域和擴展/標準巨集定義

請注意,\defand \gdefEnsure在使用巨集時\pgPtList使用計數器的值,這可能不是定義時的值。tweak\pgPtList

相反,\edefand \xdefEnsure使用定義時\pgfPtList計數器的值,即使該值同時已變更。tweak

另一方面, 和\def都是\edef本地定義。噹噹前組結束時,它們的效果也結束。

相比之下,\gdef\xdef是全球性的。它們是有效的,除非並且直到隨後的定義\pgfPtList取代它們,無論分組如何。

相關內容