使用 ifnum 和 setlength

使用 ifnum 和 setlength

我需要详细了解这行代码:

\ifnum\thetype@box=0\setlength{\spacebottom}{\expandafter\csname
spacebottom#1\endcsname}\fi

谢谢您的帮助

答案1

在我的系统上\setlength定义如下:

\setlength=macro:
#1#2->#1 #2\relax

您提供的代码片段包含#1。这似乎是在某个处理阶段可能进入宏的定义文本的内容的一部分。

假设@类别代码为 11(字母)(→ \makeatletter.. \makeatother),则序列

\ifnum\thetype@box=0\setlength{\spacebottom}{\expandafter\csname
spacebottom#1\endcsname}\fi

产量:

\ifnum触发收集第一个 TeX-⟨数字⟩-数量并从 中获取其值\thetype@box
之后\ifnum触发从 中收集关系符号=
之后\ifnum触发收集属于第二个 TeX- 的标记⟨数字⟩-数量。

因此达到了这样的阶段:

% \ifnum's matching \fi is not yet encountered.
% Value of \ifnum's first TeX-<number>-quantity and relation-sign "=" gathered/obtained.
% Process of gathering tokens that belong to \ifnum's second TeX-<number>-quantity (and afterwards 
% obtaining that quantity's value) started and in progress:
0\setlength{\spacebottom}{\expandafter\csname spacebottom#1\endcsname}\fi

找到了数字字符标记。因此,收集属于第二个 TeX 的0标记的过程\ifnum⟨数字⟩-quantity 形成收集更多数字字符标记的过程或终止收集过程的某些东西,从而扩展可扩展标记:

% \ifnum's matching \fi is not yet encountered.
% Value of  \ifnum's first TeX-<number>-quantity and relation-sign "=" gathered/obtained. 
% Digit-character-token "0" of \ifnum's second  TeX-<number>-quantity found, thus the process of
% gathering tokens that belong to \ifnum's second TeX-<number>-quantity is still in progress and now
% forms a process of gathering more digit-character-tokens or something that terminates the
% process of gathering, hereby expanding expandable tokens:
\setlength{\spacebottom}{\expandafter\csname spacebottom#1\endcsname}\fi

现在,虽然收集属于\ifnum第二个 TeX-⟨数字⟩-数量仍在进行中,宏\setlength得到扩展—我认为这应该发生在收集属于\ifnum第二个 TeX 的标记的过程中-⟨数字⟩-数量已终止

% \ifnum's matching \fi is not yet encountered.
% Value of \ifnum's first TeX-<number>-quantity and relation-sign "=" gathered/obtained. 
% Digit-character-token "0" of `\ifnum`'s second  TeX-<number>-quantity found, thus the process of
% gathering  tokens that belong to \ifnum's second TeX-<number>-quantity is still in progress and now
% forms a process of gathering more digit-character-tokens or something that terminates the
% process of gathering, hereby expanding expandable tokens:
\spacebottom⟨space-token⟩\expandafter\csname spacebottom#1\endcsname\relax\fi

现在发生什么取决于 的定义/含义\spacebottom

假设\spacebottom表示长度寄存器/长度,\spacebottom既不是数字字符标记也不是可扩展标记,因此触发终止收集属于\ifnum第二个 TeX- 的更多数字字符标记的过程。⟨数字⟩-数量。与空间令牌不同,\spacebottom不会被丢弃:

% \ifnum's matching \fi is not yet encountered.
% Value of \ifnum's first TeX-<number>-quantity and relation-sign "=" gathered/obtained.
% Digit-character-token "0" gathered as the only element of the sequence of tokens that
% forms \ifnum's second TeX-<number>-quantity. Value of \ifnum's second
% TeX-<number>-quantity obtained as "0" thereof.
% Evaluation of truth-value of statement takes place:
\spacebottom⟨space-token⟩\expandafter\csname spacebottom#1\endcsname\relax\fi

如果从 收集到的值\thetype@box不等于 的值0,则语句为假,并且直到/包括匹配的所有内容\else,或者,如果\else不存在匹配,则匹配\fi将被丢弃而不进行扩展。匹配后面的标记\else将被处理。

如果从 收集到的值\thetype@box等于值0,则该语句为真,因此标记将被处理/扩展,直到遇到匹配\else,或者在不存在匹配的情况下\else,匹配\fi

在这种情况下,将处理控制字标记\spacebottom。假设控制字标记\spacebottom表示长度寄存器/长度,LaTeX 会默默地丢弃⟨空间标记⟩并开始收集令牌,用于本地分配到该长度寄存器,从而扩展可扩展令牌。(请\setlength注意当地的分配/分配仅限于当前范围的长度寄存器,而分配则\setcounter表示全球的分配给\count所讨论的 LaTeX 计数器下的寄存器。)

\expandafter由此触发 的扩展。\expandafter如果 可扩展, 的扩展又会触发下一个标记的扩展。当下一个标记的扩展完成后, 的扩展就\expandafter完成了。从 传出的下一个标记\expandafter\csname。从 传出的下一个标记\expandafter是 标记s。因此\expandafter触发了 标记的扩展s。如果 是非s活动/不可扩展的字符标记,则不会产生任何效果。然后 的扩展\expandafter完成并达到类似于以下内容的阶段:

% \ifnum's matching \fi is not yet encountered.
% \ifnum-condition evaluated to be "true".
% Expanding/gathering tokens for the assignment to the length-register `\spacebottom` in progress:
\csname spacebottom#1\endcsname\relax\fi

现在展开\csname spacebottom#1\endcsname并且(取决于作为参数提供的内容#1)可能产生一个控制字标记。假设foo提供的是#1。在此假设下,控制字标记\spacebottomfoo被传递并达到类似于以下阶段:

% \ifnum's matching \fi is not yet encountered.
% \ifnum-condition evaluated to be "true".
% Expanding/gathering tokens for the assignment to the length-register `\spacebottom` in progress:
\spacebottomfoo\relax\fi

现在\spacebottomfoo得到全面评估,并在此得到全面扩展(如果可扩展的话)。是不可扩展的无操作,如果没有触发终止该过程,则会\relax触发终止收集令牌以分配给长度寄存器的过程。\spacebottom

当为分配收集令牌的过程终止时,分配就开始了,即\spacebottom分配了通过完全评估而得到的长度值\spacebottomfoo

然后\relax遇到无操作。

然后\fi,遇到完成/匹配的\ifnum,并将其丢弃。


删除过时的并添加一个空格,以确保正确终止收集第二个 TeX- 的\expandafter数字字符标记的过程\ifnum⟨数字⟩-quantity 您可以这样做:

\makeatletter
...
% Inside definition-text where #1 is available:
...
\ifnum\thetype@box=0 %<-The space must be as it terminates gathering 
                     %  digits after 0. It gets discarded by \ifnum.
  \setlength{\spacebottom}{\csname spacebottom#1\endcsname}%
\fi
...
% Outside definition-text:
...
\makeatother

附录——为了使这个答案完整:

正如已经指出的那样egreg 的回答

如果\thetype@box来自\newcounter{type@box},则不能确保始终以由阿拉伯数字组成的十进制数的数字字符标记形式\thetype@box提供 LaTeX 计数器的表示。type@box

宏的作用是按照用户希望在其文档文本中表示该值的方式提供相关计数器值的表示。 例如,可以定义为以罗马数字表示。 例如,可以定义为以字母表示。 例如,可以定义为以十六进制/十十二进制/八进制/(平衡)三进制/二进制数字系统或其他任何系统提供表示。\newcounter{⟨counter⟩}\the⟨counter⟩
\the⟨counter⟩
\the⟨counter⟩
\the⟨counter⟩

\value{⟨counter⟩}将以类别代码 12(其他)的一组数字字符标记的形式提供相应 LaTeX 计数器的值,这些数字字符标记形成由阿拉伯数字组成的十进制数的表示形式。

因此 — — 正如 egreg 指出的那样 — — 如果\thetype@box来自\newcounter{type@box},你最好使用\value{..}而不是\the..

\makeatletter
...
% Inside definition-text where #1 is available:
...
\ifnum\value{type@box}=0 %<-The space must be as it terminates gathering 
                         %  digit-character-tokens after 0. It gets 
                         %  discarded by \ifnum.
  \setlength{\spacebottom}{\csname spacebottom#1\endcsname}%
\fi
...
% Outside definition-text:
...
\makeatother

答案2

这是写得很糟糕的代码。

首先,\expandafter它没有任何用处并且可以(实际上应该)被省略。

这个想法是查看\thetype@box(我们无法知道它是宏还是数字寄存器)的当前含义或值。如果它是 0,那么代码将执行某些操作,否则不执行任何操作。

如果\thetype@box来自类似的东西\newcounter{type@box},那么最好不要依赖于\thetype@box,它是计数器值的表示,而不是值。

第二:好的 TeX 编程会在常量(本例中为 0)后留一个空格。在本例中,这并不是什么大问题,但在其他情况下,缺少空格可能会导致不合时宜的扩展。或者,由于代码出现在上下文中\makeatletter(因为\thetype@box),因此可以使用\z@

更好的编码将是

\ifnum\value{type@box}=0
  \setlength{\spacebottom}{\csname spacebottom#1\endcsname}%
\fi

\thetype@box如果type@box不是 LaTeX 计数器,则保留)。后面的结束行0相当于一个空格。

现在\spacebottom应该是一个长度寄存器(用\newlength或定义\newdimen)。

代码做了什么?如果存储在计数器type@box(或宏\thetype@box)中的值为 0,则条件计算结果为“真”,因此执行匹配\else或之前的代码\fi。没有\else,因此 TeX 将使用任何可能出现的情况,直到\fi

长度寄存器设置为对应于的长度\spacebottombar,假设代码是\foo具有一个或多个参数的宏的宏定义的一部分,并且调用方式如下

\foo{bar}

该宏\spacebottombar应该提前定义,否则执行\setlength命令时会出现错误。

这是因为\csname<characters>\endcsname相当于名称为反斜杠后跟的命令,<characters>\setlength{<register>}{<material>}执行的完整扩展<material>以找到合适的长度来设置<register>

相关内容