为什么我要在 \setlength 中使用 \dimexpr .. \relax?

为什么我要在 \setlength 中使用 \dimexpr .. \relax?

\dimexpr ... \relax我在某处读到过在定义长度时应该使用的内容。

真的是这样吗?用与不用似乎没什么区别:

\documentclass{article}

\newlength{\onelen}
\newlength{\twolen}
\newlength{\threelen}

\setlength{\threelen}{5em}

\setlength{\onelen}{2.5\threelen}
\setlength{\twolen}{\dimexpr2.5\threelen\relax}

\begin{document}
    a \hspace{\onelen} b
    
    c \hspace{\twolen} d
\end{document}

是否有特殊情况需要使用它或者您可以跳过它并使长度更易读?

答案1

经典 TeX 支持 dimen 值的语法<factor><internal dimen>或,请参阅 TeXbook 第 269-271 页。由于可以是十进制常数,也可以是基元声明的标记,因此以下示例在经典 TeX 中有效:<factor><internal glue><factor><internal glue>\skipdef

\newskip\twolen
\newskip\threelen  \threelen=5em\relax

\twolen=2.5\threelen \relax

这是对您的示例的提取,因为 LaTeX 宏\newlength执行\neswkip并且此宏执行\skipdef,因此从 TeXbook 的角度来看,声明的标记是“skipdef token”。 此处的<factor>2.5并且<internal glue>\threelen。由于\threelen设置为 5em,因此 的结果赋值\twolen为 2.5*5em = 12.5em。

我们可以将 解释\threelen为“声明的计量单位”,并将语法读2.5\threelen<factor>* <unit>

传统的 TeX 不再支持使用 dimen 值的计算,仅支持提到的<factor>* <unit>

eTeX 提供了一个新的原语\dimexpr <dimen expression> <optional relax>,允许进行更多维度计算,例如2em-4ex+.5\hsize

此处接受的答案并未解释为什么此处会出现“令人费解的错误消息”。事实上,该示例确实如此:

\newskip\test

\test=\dimexpr 3pt+1cm\relax plus something else

\dimexpr语创建一个<dimen>值并使用\relax从 LaTeX 宏扩展的\setlength。因此,我们得到

\test=<dimen value> plus something else

因为\test被声明为\newskip(即使用\skipdef原始),所以赋值具有语法

\test <optional equal> <dimen> <optional plus followed by stretch value> <optional minus followed by shrink value>

plus如果后面没有<dimen>,则分配以零拉伸值完成。但是我们plus在 egreg 的示例中,TeX 会排除 ,该<stretch value>必须以 开头<number>。此处没有数字,因此 TeX 会报告missing number错误。

答案2

看看\setlength

% latex.ltx, line 7668:
\def\setlength#1#2{#1 #2\relax}

现在让我们尝试一下

\documentclass{article}

\newlength{\test}

\begin{document}

\setlength{\test}{\dimexpr 3pt+1cm} plus something else

\end{document}

这将发出令人费解的错误消息

! Missing number, treated as zero.
<to be read again>
                   s
l.7 \setlength{\test}{\dimexpr 3pt+1cm} plus s
                                              omething else

总是使用\relaxto end \dimexpr,除非你 100% 确定可以省略它。

你的

\setlength{\twolen}{\dimexpr2.5\threelen}

如果出现类似plusminus以下的情况。顺便说一下,

\setlength{\onelen}{2.5\threelen}

效率更高,并且不会遇到上述问题。

相关内容