11

Relax and exhale

I'm accustomed to seeing \relax at the end of many macros. Often, I don't understand the rationale; sometimes the placement seems more or less arbitrary to me.

For example, computing a math rubber length with stretch and shrink being the half of the modulus of the natural space goes like this (based on https://tex.stackexchange.com/a/669865):

\newcommand{\flexibleMSkip}[1]{%%% 50 per cent of the modulus of the argument after plus and minus. The argument may be any integer or floating-point number.
  \mskip#1
  plus.5\muexpr\ifdim\mutoglue\muexpr#1<0pt -\fi#1\relax
  minus.5\muexpr\ifdim\mutoglue\muexpr#1<0pt -\fi#1\relax
  \relax
}

This macro is so \relaxed that it's unlikely to ever need to unload to a psychiatrist. Technically, without the first \relax, the “minus” part is ignored, but why do we need the second and third \relaxes?

Now consider the same exercise for the text mode (my own creation):

\newcommand{\flexibleHSkip}[1]{%
  \hskip#1
  plus.5\dimexpr\ifdim #1<0pt -\fi#1
  minus.5\dimexpr\ifdim #1<0pt -\fi#1
}

This one seems not \relaxed at all but causes no stress to me on small examples. Here, putting a \relax at the end of the plus line or at the end of the minus line or at the end of the whole macro (just before }) causes no difference on my small examples. Would adding these \relaxes be necessary, or cause any joy or grievance, or would it, perhaps, speed up or slow down the computation?

You may claim that the exercise 27.4 from The TeXbook demonstrates the problem in general, but in our examples above, how can we possibly misconstruct the input to cause the occurrence of unintended meaning without error at compilation?

Here is a full, somewhat less \relaxed example for you to play with:

\documentclass{article}
%%% 50 per cent of the modulus of the argument after plus and minus. The argument may be any integer or floating-point number.
\newcommand{\flexibleMSkip}[1]{%
  \mskip#1
  plus.5\muexpr\ifdim\mutoglue\muexpr#1<0pt -\fi#1\relax
  minus.5\muexpr\ifdim\mutoglue\muexpr#1<0pt -\fi#1
}
\newcommand{\flexibleHSkip}[1]{%
  \hskip#1
  plus.5\dimexpr\ifdim #1<0pt -\fi#1
  minus.5\dimexpr\ifdim #1<0pt -\fi#1
}
\showoutput
\begin{document}
\(a\flexibleMSkip{-.5mu}b\)
c\flexibleHSkip{-.1em}d
\end{document}

And, by the way, in the plus and minus expressions, why do we multiply with .5 in the front rather than diving by 2 at the end? Does it make any difference?

1

1 Answer 1

15

\relax is sometimes used as a generic non expandable token to stop scanning as in

\hsize=3in\relax

But here you are using e-tex expressions where \relax forms part of the syntax of the expression so unlike the above

\hsize=\dimexpr3in\relax

the \relax is consumed by the assignment and does not leave a \relax token in the stream.

so

\muexpr\ifdim\mutoglue\muexpr#1<0pt -\fi#1\relax

the final relax ends the (outer) \muexpr otherwise the minus at the start of the next line would form part of this expression.

Compare

\documentclass{article}
%%% 50 per cent of the modulus of the argument after plus and minus. The argument may be any integer or floating-point number.
\newcommand{\flexibleMSkipA}[1]{%
  \muskip0=#1
  plus.5\muexpr\ifdim\mutoglue\muexpr#1<0pt -\fi#1\relax
  minus.5\muexpr\ifdim\mutoglue\muexpr#1<0pt -\fi#1
  \showthe\muskip0
}

\newcommand{\flexibleMSkipB}[1]{%
  \muskip0=#1
  plus.5\muexpr\ifdim\mutoglue\muexpr#1<0pt -\fi#1
  minus.5\muexpr\ifdim\mutoglue\muexpr#1<0pt -\fi#1
  \showthe\muskip0
}


\flexibleMSkipA{1mu}

\flexibleMSkipB{1mu}

\stop

which shows removing the \relax changes the value

> 1.0mu plus 0.5mu minus 0.5mu.
\flexibleMSkipA ...0pt -\fi #1 \showthe \muskip 0 
                                                  
l.18 \flexibleMSkipA{1mu}
                         
? 
> 1.0mu plus 0.5mu.
\flexibleMSkipB ...0pt -\fi #1 \showthe \muskip 0 
                                                  
l.20 \flexibleMSkipB{1mu}
                         
? 


On your unrelated 2nd question prefixing with 0.5 is a classic tex <factor> and halves the natural length, discarding plus and minus components. /2 is e-tex division and halves all components.

\showthe\thickmuskip
\showthe\muexpr.5\thickmuskip\relax
\showthe\muexpr\thickmuskip/2\relax

produces

> 5.0mu plus 5.0mu.
> 2.5mu.
> 2.5mu plus 2.5mu.
17
  • 1
    @Slurp Not really, as explained in the answer \relax is part of the syntax in the case of \muexpr, as the \muexpr does consume the \relax.
    – user202729
    Commented Jan 23, 2023 at 20:04
  • 1
    @Slurp no for a classic assignment what you say is true but for \muexpr, \dimexpr etc an optional \relax is part of the expression syntax and is consumed unlike any other non expandable token which stops the scan but then is re-inserted. Commented Jan 23, 2023 at 20:06
  • 1
    @AlbertNash \dimexpr is identical to \muexpr in all ways including \relax handling. the only difference is the units allowed. so your hskip example missing \relax is like my B example, it is error free but does not represent the length you intend Commented Jan 23, 2023 at 20:25
  • 2
    @Slurp but the \relax in the OPs example are necessary, as my A and B examples show. If you miss them out you get no error but get the wrong length Commented Jan 23, 2023 at 20:27
  • 1
    @AlbertNash I added a note re 0.5 and /2 Commented Jan 23, 2023 at 20:35

You must log in to answer this question.