下面显示了取自的代码片段multido.tex
。我注意到作业不是以结尾的%
。
参见
\dimen@=#1\advance\dimen@#2
\def\multido@step@d#1#2{% \dimen@=#1\advance\dimen@#2 \edef#1{\number\dimen@ sp}}%
再次
\count@=#1\advance\count@ by #2
参见\def\multido@step@i#1#2{% \count@=#1\advance\count@ by #2 \edef#1{\the\count@}}
再 看看
\dimen@=#1pt
,\dimen@=#2pt
在\dimen@=#1pt\advance\dimen@#2
\def\multido@init@r#1#2#3{% \dimen@=#1pt \multido@dimtonum\dimen@#3% \dimen@=#2pt \ifnum\multido@count<\z@\dimen@=-\dimen@\fi \multido@addtostep{\do\multido@step@r{\do#3}{\number\dimen@ sp}}} \def\multido@step@r#1#2{% \dimen@=#1pt\advance\dimen@#2 \multido@dimtonum\dimen@#1}
作业是否会产生必须以 结尾的尾随空格%
?
答案1
示例 1
\def\multido@step@d#1#2{%
\dimen@=#1\advance\dimen@#2
\edef#1{\number\dimen@ sp}}%
之后#2
应该有\relax
。事实上,如果#2
是寄存器或参数(例如\z@
或)\lineskip
,则行尾提供的空间将不是将被忽略。在这种情况下也%
可能被使用,因为以下标记是不可扩展的(\edef
)。从获得的标记列表\multido@step@d{\x}{2pt}
将是(我用•表示空格标记)
\dimen@=\x\advance\dimen@2pt•\edef\x{\number\dimen@ sp}
并且之前的空格\edef
将被忽略。但是使用 `\multido@step@d{\x}{\parindent} 则
\dimen@=\x\advance\dimen@\parindent•\edef\x{\number\dimen@ sp}
而太空标记将不是将被忽略。它位于控制字之后这一事实无关紧要:标记化阶段已经发生。后面\relax
有#2
将会\relax
代替空格标记。
示例 2
都一样。\relax
后面应该有#2
示例 3
为了清楚起见,我将对行进行编号。
1 \def\multido@init@r#1#2#3{%
2 \dimen@=#1pt
3 \multido@dimtonum\dimen@#3%
4 \dimen@=#2pt
5 \ifnum\multido@count<\z@\dimen@=-\dimen@\fi
6 \multido@addtostep{\do\multido@step@r{\do#3}{\number\dimen@ sp}}}
7 \def\multido@step@r#1#2{%
8 \dimen@=#1pt\advance\dimen@#2
9 \multido@dimtonum\dimen@#1}
没有必要用 来终止第 2 行和第 4 行%
;实际上,%
第 4 行末尾的 是错误的,因为 TeX 会\ifnum
在执行分配给 之前开始扩展\dimen@
(在这种特殊情况下可能无害)。
与之前相同的问题出现在第 3 行:%
这里的是好的,因为下面的标记是\dimen@
无法扩展的;\relax
会更好。
出于与之前相同的原因,第 8 行应该\relax
在末尾有;而不是,因为诸如的%
参数会在执行分配之前触发扩展。#2
2pt
\multido@dimtonum
答案2
当 TeX 扫描维度时,除非存储的数量以寄存器的形式呈现,否则它将继续寻找数字和单位(沿途扩展),直到到达空格或不适当的字符。空格被删除;因此,按功能显示编写的赋值在删除以下空格方面具有与控制字相同的行为。当然,如果维度是一个寄存器,那么寄存器名称要么是一个控制字本身(从而吞噬空间),要么是一个 TeX 将扫描的数字......
这就是说,一些您展示的分配使用参数(如#2
)表示维度。一些狡猾或过于聪明的人可能会使用寄存器来实现这一点,这样空间就不会被占用,因为它会在读取控制字之前写入宏定义。实际上,当此类数据不受程序员控制时,最好使用 来消除空间\relax
。