Why does \dimexpr swallow \relax?

To add to what Hendrik says, I think the overall point was that \numexpr, \dimexpr, etc. can be used in a full expansion context without leaving a stray \relax or space:

\edef\example{\the\dimexpr 10 pt + 20 pt \relax}

gives \example defined as 30pt with no unexpected tokens. That is in many ways much 'neater' than the alternative of leaving the \relax in place. The same argument does not apply to TeX's setting of registers as that is never expandable, so the issue does not arise.

(Of course, for a definitive answer you would need to ask the members of the NTS team who actually wrote this code.)


I would say this makes it easy to delimit a \dimexpr in a fully expandable way. Putting a \relax is a usual way to delimit TeX dimensions, which I learned the hard way: It's always a good idea to put a \relax after something like \hskip1pt. Now it seems that eTeX just made a principle out of this.

(An alternative is to put a space to delimit a TeX dimension, but firstly a \relax is a lot more visible, and secondly it's sometimes not so easy to put a space, namely after a control sequence. As Bruno points out in his comment, spaces cannot be used to delimit \dimexpr and friends.)


For the same reason as TeX gobbles a trailing spaces from numbers. In the case of TeX, this is needed to stop a number cleanly and make sure that in all cases it will be terminated without expanding anything further nor inserting a blank space. In fact, TeX probably skips spaces after control words (multiletter control sequences) for the same reason (although that happens at a different stage of processing). The idea is that it should always be possible to "stop without inserting anything".

Example: \ifdigit below tests whether the argument is a digit. The space after #1 is required to stop TeX from expanding the first \expandafter prematurely. On the other hand, we don't want the space to end up in the output. So in that case at least, TeX's space gobbling is a feature.

\long\def\ifdigit#1{%
    \ifnum 9<1\string #1 %
        \expandafter\@firstoftwo
    \else
        \expandafter\@secondoftwo
    \fi}

eTeX's designers could decide that a space stops the \numexpr or \dimexpr, because they simply use TeX's procedures to read operands. And these procedures already remove a trailing space. eTeX does not see the space before + in \numexpr 1 + 2. It would have been technically possible to let \numexpr be stopped by two space tokens in a row, and gobble them, but that would be very difficult to input, since two space characters in a row are equivalent to one. Some other delimiter had to be chosen. It had to be non-expandable, preferably already there in the language, and it had better do nothing when used outside a \...expr situation... No need to add a new primitive: \relax was a natural choice.

Now consider a \compareint function defined as follows

\long\def\compareint#1#2#3{%
    \ifnum\numexpr#1\relax#2\numexpr#3\relax
        \expandafter\@firstoftwo
    \else
        \expandafter\@secondoftwo
    \fi}
\compareint{1+2}<{3-1}{Yes}{No}

In this particular case, leaving \relax behind would not be a problem. However, think of nesting this:

\def\X{345}\def\Y{534}
\compareint {132} < {\compareint{12}>{9}{\X}{\Y}+1} {Yes} {No}

If the \relax was not removed from the internal \compareint, it would stop expansion of the outside \compareint too early (actually, before expanding to \X or \Y, so that would be a problem).