在这答案,egreg 指出“LaTeX 计数器应始终进行全局修改”。 但是,那电子工具箱包提供了\defcounter
宏,它将为先前初始化的计数器分配一个值本地(但可以以 为前缀)。我一直在使用这个宏,例如,来更改组内计数器\global
的值:secnumdepth
\documentclass{article}
\usepackage{etoolbox}
\begin{document}
\section{bla}
\begingroup
\defcounter{secnumdepth}{-2}
\section{blubb}
\endgroup
\section{foo}
\end{document}
\defcounter
那么:egreg 关于始终全局修改计数器的说法正确吗?如果正确,为什么?如果不是,那么在我的 MWE 中使用 是否仍然是不好的做法?
答案1
与 (La)TeX 一样:如果您知道自己在做什么,那么您就可以去做!
一些本地计数器的改变非常有意义,就像问题中的例子一样。但是我不会称之为secnumdepth
真正的计数器。毕竟它永远不会增加。这里只是使用了一个计数器寄存器来存储整数,因为没有其他合适的类型。用于分段命令、列表或其他内容的真正的 LaTeX 计数器通常应该是全局的,因为它们表示的计数会覆盖整个文档,而不仅限于本地组。如果您需要为您的代码使用本地计数器,那么您通常已经知道\newdimen
并且可以定义 TeX 计数器而不是 LaTeX 计数器。
在我看来,对全局计数器进行局部重新定义的一个很好的例子是我的回答多个章节中的交叉引用。我使用{\value{chapter}=<value>\relax\thechapter}
(这是一种肮脏的黑客手段)这样我可以使用当前\thechapter
格式,但使用与当前不同的章节号。
PS:我通常按照“一旦全局化,永远全局化!”的规则进行编码,除非出现如上所述的特殊情况。
答案2
感谢 egreg 指点我TeX 按主题分类。相关引述如下(第 275 页):
分配给组内的数量必须在该组结束后恢复。保存堆栈是保存要恢复的值的地方;保存堆栈的大小限制了可以恢复的值的数量。
交替对某个值进行全局和局部赋值将导致“保存堆栈累积”:对于全局赋值之后的每个局部赋值,都会保存变量的先前值。因此,交替进行此类赋值将导致保存堆栈上项目的不必要增多。
答案3
由于 TeX 堆栈的性质,你应该在本地或全局使用寄存器。使用原语,这意味着
\newcount\mylocalcount
\newcount\myglobalcount
\begingroup
\mylocalcount 10 %
\global\myglobalcount 10 %
\endgroup
因此,如果您想使用它\defcounter
进行本地分配,则不应将其与\setcounter
同一个计数器混合。
在 LaTeX3 中,我们通过为变量添加\l_...
和\g_...
前缀将其形式化。