5

I was surprised to find that the argument of an \unexpanded is expanded if the \unexpanded is within the first two tokens after an \if. Using Knuth TeX's \noexpand instead works but I am curious where the difference is.

\documentclass{article}

\begin{document}

    \def\endtoken{~}

    \typeout{! ========== tracing 1 ==========}
    \tracingmacros=2
    \tracingcommands=3

%   \if \expandafter\noexpand\endtoken \noexpand~% this would work
    \if \unexpanded\expandafter{\endtoken} \noexpand~% this does not
        true
    \else
        false
    \fi

    \tracingcommands=0
    \tracingmacros=0
    \typeout{! ========== tracing 0 ==========}

\end{document}

The \expandafter which expands the argument of the \unexpanded once makes no difference. ~ is expanded all the way with or without it and the result is the same.

\tracingmacros shows how ~ is expanded and \tracingcommands shows that \if evaluates to true. I am assuming that it comes to this result by comparing \protect and \unhbox which are both inserted by expanding ~ and are equal because they are both control sequences. Is there a tracing command which would show which tokens TeX compares when evalutaing a conditional? (I have scanned through the great list of tracing commands but have not found this among it unfortuantely.)

(The exclamation mark at the beginning of the \typeout makes TeXstudio think there was an error so that it provides me with a link to the position in the log file where the output of the tracing commands begins and ends. This may, however, have the unintended side effect that it does not load the pdf although it has been built correctly.)

Why is the argument of \unexpanded expanded after an \if (not inside of an \edef) but a token following a \noexpand is not expanded, even after an \if?

The interesting question Get the lion to run in loops. Tersely. also deals with \if and \unexpanded but I think it does not answer this question because there the \fi is in the <filler> of \unexpanded but here after the <balanced text> and the closing curley brace.

  • I think the difference between \noexpand and \unexpanded is worth detailing, but @egreg is right that the test here is ... not really correct – Joseph Wright Jun 27 '19 at 10:44
7

The \unexpanded primitive is essentially an anonymous toks, which means no expansion _within an \edef or similar, whereas \noexpand explicitly changes the behaviour of the next token to be equal to \relax for one expansion. This is perhaps easier to see if we choose to typeset the results of the two:

\documentclass{article}
\begin{document}
\newcommand{\demo}{FOO}
Text \noexpand\demo\space text \unexpanded{\demo} text.
\end{document}

The first \demo is turned into \relax for this reading, and so does nothing. In contrast, the second is effectively passed through \toks0{\demo}\the\toks0, and so typesets normally.


As egreg points out, one can also see the effect in

\documentclass{article}
\begin{document}
\expandafter\edef\expandafter\foo\expandafter{\unexpanded{~}} 
\show\foo
\expandafter\edef\expandafter\foo\expandafter{\noexpand~}
\show\foo
\end{document}
  • In expl3 code this is important where we return tokens protected from expansion: we always use \unexpanded in case we are not inside an e/x-type context. – Joseph Wright Jun 27 '19 at 10:45
  • Do I understand it correctly that \unexpanded behaves as if it would save the balanced text in a toks register (as described in TeX by Topic Chapter 14: Token Lists) and then inserts it like with a \the (except that this does not influence any of the registers that you can access with \the)? So the balanced text is not expanded if \unexpanded is expanded by \edef (or \xdef) but expanded anywhere else? – jakun Jun 27 '19 at 12:15
  • @jakun Exactly: the code is that for a toks, just without the need to assign to a real one – Joseph Wright Jun 27 '19 at 12:25

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.