5

The unravel package defines an \__unravel_special_relax: command, for which we find in the documentation the following:

A special marker slightly different from \relax (its \meaning is \relax but it differs from \relax according to \ifx). In the right-hand side of our assignment, \__unravel_special_relax: could be replaced by any other expandable command.

\exp_after:wN \cs_new_eq:NN
\exp_after:wN \__unravel_special_relax:
\exp_not:N \__unravel_special_relax:

How exactly is \__unravel_special_relax: different from \relax? What is the trick behind this definition? And why is this special \relax version needed in the unravel package?

7

If we show the definition in old money:

\documentclass{article}

\begin{document}

\expandafter\let\expandafter\zrelax\noexpand\zrelax
\show\zrelax
\show\relax

\ifx\relax\zrelax
 \show Y
\else
 \show N
\fi

\end{document}

produces a terminal output of

> \zrelax=\relax.
l.6 \show\zrelax

? 
> \relax=\relax.
l.7 \show\relax

? 
> the letter N.
l.12  \show N

? x

so \zrelax shows as \relax but is ifx not equal to \relax. It is the (normally) internal frozen temporary "relax"definition that is used to implement \noexpand which makes the command act like an unexpandable \relax token just temporarily for one expansion step, but Bruno's trick here grabs that definition with the \expandafter and \let construct,

  • Could you elaborate on why this special \relax is needed/in what situations it is useful? – siracusa Nov 19 at 18:26
  • @siracusa it's never useful in anything approaching normal code, but Bruno needs it as unravel tries to emulate tex execution and that's what tex adds, frozen \relax get used in other places as well as \noexpand in particular some uses of missing branches in if tests. – David Carlisle Nov 19 at 18:30

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.