\countdef\mycount= 的注意事项以及 LaTeX 中的 \newcount 与 \newcounter{}

\countdef\mycount= 的注意事项以及 LaTeX 中的 \newcount 与 \newcounter{}

让我们澄清这在 LaTeX 中是一个坏主意,然后澄清在 LaTeX 中vscountdef\mycount=<number>的适当用法。\newcount\mycount\newcounter{mycount}

背景:我去年才开始学习 TeX,不久之后,我就厌倦了从头开始学习一切。每个人都知道阅读 TeXBook 是什么感觉。任何时候,我手边都有这本书,中间夹着大约 10 个纸板书签,从一个书签跳到另一个书签,参考索引,添加更多书签,驱使自己找到某种解决方案。

countdef\mycount=<reg number>在第 119 页发现了这一点,Knuth 只是告诉你如何使用它们,没有任何警告。所以,作为一个天真的新手,我使用了它们,我的解决方案有效,我没有必要再进一步研究。一段时间后,在使用 LaTeX 时,我从记忆中挖出了这一点,并在使用它时遇到了麻烦。我发现了这一点,\newcounter{mycount}没有回头。

现在我正在更深入地研究这个问题,我需要再次提出这个问题。在我最初努力理解 Plain-TeX 的时候,如果我继续读到第 121 页,Knuth 在那里解释了 的重要性\newcount,我现在就不会问这个问题的第一部分了。TeXBook 是一本庞大而复杂的书,我认为提出这个问题有助于提高人们对深入研究 Plain-TeX 的“年轻玩家陷阱”之一的认识。

希望这能解释我最初是如何犯下如此根本性错误的,并指出其他人也可能犯同样的错误。此外,由于在创建 LaTeX 解决方案时使用 Plain-TeX 有很多用处,我真的很想知道在 LaTeX 中使用\newcountvs的注意事项\newcounter{}

答案1

这是个坏主意

\countdef\mycount=81

全部TeX 的风格。不允许讨论。

Plain TeX 分配了 25 个计数寄存器;可以从您机器上的任何tex.log(或plain.log) 检查。因此,如果宏包说

\newcount\foo

TeX 将在内部执行\countdef\foo=26,但实际数字应该绝不被使用。因此,假设您加载了eplain其他宏包;它们将分配新的计数器,也许它们将使用其中的 56 个。当您执行 时\countdef\mycount=81,任何后续赋值都\mycount将破坏宏包假设计数器保存的值。或者宏调用将破坏该值正在指望。

这样做\newcount\mycount(在 LaTeX 中也有效,但应谨慎使用并且只能在包代码中使用)就不会出现这样的问题。

供您参考,LaTeX 分配的最后一个计数器是 78 号。其他 11 个由 分配amsmath。您看到问题了吗?计数器 81(如果amsmath是第一个调用的包)将是\classnum@,这是 的一个非常重要的内部寄存器amsmath。混乱随之而来。


让我们解决‘\newcount相对\newcounter' 问题。前者是 Plain TeX 构造,也由 LaTeX 导入,而后者是 LaTeX 特有的。使用\newcounter{foo}[baz]一个创建一个 LaTeX 计数器foo,该计数器添加到重置列表柜台baz;一个例子是

\newcounter{section}[chapter]

这是由book类完成的。添加“父”计数器是可选的。在\newcounter{foo}声明(带或不带可选参数)之后,LaTeX 定义

  1. \c@foo通过\newcount\c@foo
  2. \thefoo通过\newcommand\thefoo{\arabic{foo}}

并且\p@foo(但描述这一点太过技术性)。

我们可以使用命令\arabic{foo}\alph{foo}\Alph{foo}\roman{foo}\Roman{foo}\fnsymbol{foo}获取计数器当前值的表示。最重要的是,我们可以使用

\stepcounter{foo}
\addtocounter{foo}{<number>}
\setcounter{foo}{<number>}

\refstepcounter{foo}

来更改当前值。我输入了证据中的最后一个命令,因为它不仅会步进计数器,而且(本地)定义,\current@label以便下一个\label命令将引用此值(更准确地说,是值的当前表示)。

为了表现得好\label-\ref机制良好地运行,全部上述计数器操作(使用名为 的分配寄存器\c@foo)是全球的

在大多数文档中,不需要使用寄存器进行涉及乘法和除法的算术运算,因此在用户级别没有定义宏\multiplycounter\dividecounter

如果包需要进行算术运算,则\newcount可以使用直接定义的 TeX 计数器,使用基元\advance\multiply和进行局部或全局计算\divide。几个包使用 TeX 计数器(我使用此名称来代替上面描述的“LaTeX 计数器”)。

由于 LaTeX 计数器固有的全局特性,使用\multiply或对其进行操作是不好的做法\divide:对寄存器的操作应始终是本地的或始终是全局的。因此\global\multiply\c@foo by 2应在以下情况下使用真的需要,根据我的经验,这是非常罕见的。

相关内容