7

I read somewhere that you should use \dimexpr ... \relax when defining lengths.

Is that really the case? There seems to be no difference between using it or not:

\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}

Are there specific circumstances where you should use it or can you skip it and make the length more readable?

2
  • 2
    @mrCarnivore Additions are possible without \dimexpr, but this requires to load package calc that redefines \setlength to support some simple arithmetic. May 25 at 22:58
  • \dimexpr … \relax does not make sense in your example. But if you have something like \newcommand*{\foo}[1]{…\setlength{\bar}{#1}…} you could add extra functionality using \dimexpr #1\relax — if you want and if it makes sense. See the eTeX manual section 3.5 for more information about \dimexpr, \numexpr and \glueexpr.
    – cabohah
    May 26 at 6:46

2 Answers 2

4

The syntax <factor><internal dimen> or <factor><internal glue> for a dimen value is supported by classical TeX, see TeXbook pages 269-271. Because <factor> can be decimal constant and <internal glue> can be a token declared by \skipdef primitive, the following example is valid in classical TeX:

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

\twolen=2.5\threelen \relax

This is an extraction of your example, because the LaTeX macro \newlength does \neswkip and this macro does \skipdef, so the declared token is "skipdef token" from TeXbook's point of view. The <factor> is 2.5 here and <internal glue> is \threelen. Because \threelen was set to 5em, the resulting assignment to \twolen is 2.5*5em = 12.5em.

We can interpret the \threelen as "a declared unit" of measure and read the syntax 2.5\threelen as <factor>*<unit>.

Classical TeX supports no more calculation with dimen values, only the mentioned <factor>*<unit>.

eTeX gives a new primitive \dimexpr <dimen expression> <optional relax> which allows to do more dimen calculations, like 2em-4ex+.5\hsize.

The accepted answer here doesn't explain why the "puzzling error message" occurs here. The example does, in fact:

\newskip\test

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

The \dimexpr primitive creates a <dimen> value and consumes the \relax expanded from LaTeX macro \setlength. So, we get

\test=<dimen value> plus something else

Because \test was declared as \newskip (i.e. using \skipdef primitive), the assignment has syntax

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

If there is no plus after the <dimen>, the assignment is finalized with zero stretch value. But we have plus here in egreg's example, then TeX excepts the <stretch value> which must begin by <number>. The number isn't present here, so TeX reports missing number error.

10

Look at the definition of \setlength

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

Now let's try

\documentclass{article}

\newlength{\test}

\begin{document}

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

\end{document}

This will issue the puzzling error message

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

Always use \relax to end \dimexpr, unless you are 100% sure that you can omit it.

It would be the same with your

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

if something like plus or minus follows. By the way,

\setlength{\onelen}{2.5\threelen}

is way more efficient and will not run into the problem described above.

1
  • So \relax is necessary (when using additions and therefore needing \dimexpr) but if you are only using multiplication then you can (and should) leave out \dimexpr and \relax? May 26 at 4:15

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .