17

I was wondering how \etoolbox's \expandonce does what it does. So I looked up how it was defined and found

\unexpanded\expandafter{#1}

But no matter where I look, I cannot find a definition for \unexpanded. I've tried

 texdef -t latex unexpanded -s

which returns the following:

Source code definition of 'unexpanded' could not be found.
\unexpanded is defined by (La)TeX.

\unexpanded:
\unexpanded

I've also tried looking in the source2e documentation, but there's nothing there about \unexpanded.

Could someone point me in the right direction of where to find the documentation?

  • I think the texbook goes over it, but I can't quite remember. You won't find it in source2e. – Sean Allred Oct 26 '13 at 15:55
  • 2
    \unexpanded is an eTeX primitive, have a look at the eTeX manual – clemens Oct 26 '13 at 15:55
  • @cgnieder That's the answer here: please post as such – Joseph Wright Oct 26 '13 at 16:03
  • @cgnieder How do I find the source code for eTeX stuff? Or how would I used texdef to show the source code? – A.Ellett Oct 26 '13 at 16:04
  • 1
    @A.Ellett Trying to use texdef for \unexpanded is the same as trying to use it for say \def or \relax: you won't get anything. As it's a primitive, the source is in WEB (a form of Pascal), but unless you really need the detail then I'd go with the engine manual (eTeX in this case). – Joseph Wright Oct 26 '13 at 16:17
21

\unexpanded is an ε-TeX primitive. If you do

\documentclass{article}
\begin{document}
\show\unexpanded
\end{document}

you'll get in the log:

> \unexpanded=\unexpanded.
l.3 \show\unexpanded

which seems to be redundant information but actually tells you that it is a primitive control sequence. Primitives are listed in the TeX Book or TeX by Topic but you won't find \unexpanded there because it is an ε-TeX primitive. It is described in the e-TeX manual, though:

\unexpanded<general text>.

The expansion is the token list <balanced text>.

[...]

When building an expanded token list, the tokens resulting from the expansion of \unexpanded are not expanded further (this is the same behaviour as is exhibited by the tokens resulting from the expansion of \the<token> variable in both TeX and ε-TeX).

16

As cgnieder's excellent answer says, \unexpanded is a primitive of e-TeX, that is, an extension of the original TeX language. Primitives don't have a definition, they're commands directly understood by the engine. Some of them are expandable, that is, they don't reach TeX's “stomach” because they are expanded just like macros (the same happens to the conditionals, for example); \unexpanded is one of these macros.

It's a generalization of \noexpand which, in the context of an \edef or a \write, has a null expansion but also the effect of making the next token unexpandable for the task at hand. Thus

\def\foo{something}
\def\baz{else}
\edef\x{\foo\noexpand\baz}

would be equivalent to

\def\x{something\baz}

With \unexpanded you can protect from expansion in an \edef (or \xdef) or \write an entire token list, without the need to prepend \noexpand to all expandable tokens.

Since \unexpanded follows the pattern

\unexpanded <general text>

it has an interesting feature. When TeX wants to expand it, it looks forward to find a <general text> which is defined as

<filler> { <balanced text> <right brace>

and expands tokens to recognize a <filler> and, eventually, the {. A <filler> is just an arbitrary sequence of \relax and space tokens which are simply ignored. The { is an explicit or implicit token of category code 1.

A consequence of this is that

\unexpanded\expandafter{\cs}

will cause the expansion of \cs before the { that starts the list of tokens which will not be expanded any more. Indeed, the definition of \expandonce is

\newcommand{\expandonce}[1]{\unexpanded\expandafter{#1}}

Also \detokenize (another expandable primitive of e-TeX) has the same properties.

Beware of the <filler>: it can cause some unexpected effects under certain circumstances as shown in Get the lion to run in loops. Tersely

  • In an expansion context, things like \def, \expandafter, \noexpand are treated as though their expansion was \relax, right? So, in the context of \unexpanded, when expanding the <filler>, TeX finds \expandafter, expands it and sees what amounts to \relax. Am I understanding this correctly? – A.Ellett Oct 26 '13 at 19:44
  • 1
    @A.Ellett Sorry, you're not understanding this correctly. In an expansion context, unexpandable tokens are simply not expanded (they can't be); \expandafter and \noexpand are expandable and they are expanded. The expansion of both is null, but before this null expansion, they do their respective action. – egreg Oct 26 '13 at 20: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.