Following the comments at Doing maths with distance values in LaTeX source code:

+1 for teaching me that \dimexpr can optionally swallow a \relax. Yesterday I tried to use \relax as a delimiter for \numexpr, and I just couldn't understand why the \relax is gone although it's not expandable. – Hendrik Vogt Feb 18 at 9:32

@Hendrik: Yeah, I think you need two \relax then. I find the \relax swallowing extremely useful. Its friends like \numexpr do the same. – Martin Scharrer♦ Feb 18 at 9:36

and with this issue being touched on again by the answers of Joseph and Martin at Which is better: a dimension or a macro?, I ask myself why does Etex do things this way? I find it unintuitive and I don't see how it can be useful to avoid carrying out a no-operation command.

  • 1
    Well, one alternative would be something like TeX' "keep on expanding until you find something you don't expect" semantics when parsing values, which is ... well, it's intuitive once you've gotten used to it. ;) Jun 10 '11 at 12:31
  • (I just left this as a comment on the original, but it could do with being here as well) Can we clarify that "optionally" in the first quoted sentence? Is it really optional? Jun 10 '11 at 12:52
  • @Andrew: \dimexpr, etc. are terminated by the first token which cannot form part of an appropriate number. So something like a letter will terminate \numexpr without needing a \relax. So it is optional.
    – Joseph Wright
    Jun 10 '11 at 13:26
  • @Joseph: It wasn't whether the \relax is optional but whether the swallowing was optional. Jun 10 '11 at 14:33
  • 2
    @Andrew: Ah, I see. In that case, it should perhaps read 'swallowing an optional \relax', as the swallowing itself is not optional.
    – Joseph Wright
    Jun 10 '11 at 15:51

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.)

  • 7
    IIRC, that was indeed one of the main reasons for doing it this way. Jun 10 '11 at 14:11
  • It's the "much 'neater'" that I am having difficulties with. The expected semantics of \relax is to have a do nothing token survive the expansion process to be looked at and discarded by the backend. Etex would be faithful to this intuition if it took the \relax token from the input stream, did its work, and then put the token back. Then, for instance, a very experienced TeXnician like Hendrik would not have got into difficulty. How is this not neater? Jun 11 '11 at 11:28
  • 1
    @Charles: 'Neater' is of course subjective. To me, it's neater that \example ends up as a length and nothing else, so I can compare a number I type in with one that is calculated (using two macros and \ifx). \relax is not itself part of the number, so to me should be 'tided up' inside an \edef. As I say, this is a subjective thing, and I certainly had nothing to do with writing e-TeX.
    – Joseph Wright
    Jun 11 '11 at 14:10
  • 1
    @CharlesStewart I understand what you mean; perhaps it would have been neater to have these expressions be (optionally) terminated by a different token like \endexpr instead of reusing \relax; that way we'd have the best of both worlds: the \edef in this answer (with \endexpr in place of \relax) would still work, and if you really wanted \relax for some reason then that would remain too. But IMO the current solution is fine, and one can just adopt a habit of always ending a \dimexpr with \relax. (So if you do want a \relax that stays, you just have two \relax.) Feb 6 '18 at 20:58

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.)

  • 3
    A space delimits a dimension, but cannot stop \dimexpr. One somewhat surprising case is \the\numexpr 1+2 3+4, which expands to 33+4: the number 2 is stopped by a space, and the 3 does not fit at that place in the \numexpr, which is thus stopped. A similar example can probably be built for \dimexpr. Jun 10 '11 at 14:25
  • @Bruno: Thanks a lot for pointing this out! Is it better with my edit? Jun 10 '11 at 15:46
  • yes, that's correct. Jun 10 '11 at 17:16

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.

    \ifnum 9<1\string #1 %

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


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

\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).

  • In \compareint, you can miss out the first \relax as #1 will be terminated by the comparator #2.
    – Joseph Wright
    Jun 10 '11 at 14:44
  • @Joseph: that's true. I hesitated when posting, but I think that putting \relax makes slightly clearer the fact that #2 is the comparison character. It also provides somewhat better error checking (against input like \compareint{1+2}{3}... where the user forgets the comparison). I should have said that this is taken directly from l3int (which doesn't have the first \relax). Jun 10 '11 at 15:12
  • I know the relax is not in l3int, that's why I commented :-)
    – Joseph Wright
    Jun 10 '11 at 15:15
  • @Joseph. I just did some speed comparison. On 10000000 \int_compare:nNnTF, I get 116 seconds both with and without the first \relax. So we may want to put it in l3int. I think the reason why it makes no speed difference is that in both cases two tokens are read. With \relax, \relax is read and swallowed, and then the comparison character, and without, the comparison character is seen, put back, and re-read. Jun 10 '11 at 17:30

Actually, the single paragraph of documentation in the e-TeX manual already answers this question with an illustrative example, which surprisingly has not been mentioned in the answers here. The example given there is:

\ifdim\dimexpr (2pt-5pt)*\numexpr 3-3*13/5\relax + 34pt/2<\wd20

as equivalent to \ifdim 32pt < \wd20. In this case, the inner \numexpr 3-3*13/5\relax expands to -5 (note rounding), so that the outer \dimexpr becomes equivalent to (-3pt) * (-5) + 17pt. If the \relax were not swallowed, and were instead left on the input stream, then the outer \dimexpr would also get terminated at the \relax, resulting in errors.

For completeness, reproducing the documentation of the grammar here, lightly reformatted:

e-TeX introduces the notion of expressions of type number, dimen, glue, or muglue, that can be used whenever a quantity of that type is needed. Such expressions are evaluated by e-TeX’s scanning mechanism;

  • they are initiated by one of the commands \numexpr, \dimexpr, \glueexpr, or \muexpr (determining the type t) and optionally terminated by one \relax (that will be absorbed by the scanning mechanism).

  • An expression: consists of one or more terms of the same type to be added or subtracted;

  • a term of type t: consists of a factor of that type, optionally multiplied and/or divided by numeric factors; finally

  • a factor of type t: is either a parenthesized subexpression or a quantity (number, etc.) of that type.

Thus, the conditional

\ifdim\dimexpr (2pt-5pt)*\numexpr 3-3*13/5\relax + 34pt/2<\wd20

is true if and only if the width of box 20 exceeds 32 pt .

Note the use of \relax to terminate the inner (numeric) expression, the outer (dimen) expression is terminated automatically by the token <₁₂ that does not fit into the expression syntax.

And then there are a couple more paragraphs about arithmetic (e.g. rounding), and how this is expandable.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.