[Tex/LaTex] Manually expanding a macro within a definition

expansionmacros

When defining macros using \edef (which by default expands every macro within the definition as much as possible), I can declare some macro within that definition to not expand by using \noexpand before that macro. So \noexpand could be seen as declaring an exception to the default behavior of expanding everything.

However, sometimes I only want very few commands to be expanded. Now when I define a macro using \def, the default behavior is to not expand anything within the definition (at the point of the definition – it may of course later be expanded after the new macro has been expanded somewhere). Is there a command for manually expanding a macro (fully or just one step) at the point of definition when defining it using \def or any other definition command such that normally macros are not expanded (in analogy to declaring an exception as with \noexpand within \edef)? If so, what is the command and its exact effect?

To illustrate the question by an example, I can have the following code using \edef:

\documentclass{article}

\newcounter{mycount}

\edef\foo{\noexpand\textit{\arabic{mycount}}}

\stepcounter{mycount}

\begin{document}

Before: \foo

After: \arabic{mycount}

\end{document}

The output is:

Before: 0

After: 1

My question is whether there is a command \doexpand (or whether such a command could be defined) such that the following code would yield the same result:

\documentclass{article}

\newcounter{mycount}

\def\foo{\textit{\doexpand\arabic{mycount}}}

\stepcounter{mycount}

\begin{document}

Before: \foo

After: \arabic{mycount}

\end{document}

EDIT: Some alteration of the last code would be ok. My restriction is not to use \def but to have any way of defining a macro such that macros within that definition are normally not expanded as long as they are not "marked" somehow to be expanded.

Best Answer

When TeX absorbs the replacement text of a macro for \def it performs no expansion whatsoever. To the contrary, when it does \edef it expands every expandable token recursively, with some exceptions.

The exception is that tokens resulting from the expansion of \the<token register> are not expanded further. The same for tokens resulting from \unexpanded, that's very similar to using an unnamed token register. The expansion of \noexpand is empty, but it makes the next token temporarily equivalent to \relax, so it's not expanded further.

This seems to exclude the possibility of doing \doexpand. However you can use regular expressions: change every control sequence <cs> into \noexpand<cs> and then change \noexpand\doexpand\noexpand into nothing.

There are several limitations in the following implementation of \pedef (partial \edef): \doexpand must precede a control sequence and active characters are not covered; also parameters to the macro are not allowed, so it's just a proof of concept.

\documentclass{article}
\usepackage{xparse,l3regex}

\newcounter{mycount}
\setcounter{mycount}{42}

\ExplSyntaxOn
\cs_new_protected:Npn \pedef #1 #2
 {
  \tl_set:Nn \l_tmpa_tl { #2 }
  \regex_replace_all:nnN { (\cC.) } { \c{noexpand}\1 } \l_tmpa_tl
  \regex_replace_all:nnN { \c{noexpand}\c{doexpand}\c{noexpand} } { } \l_tmpa_tl
  \cs_set:Npx #1 {\l_tmpa_tl}
 }
\ExplSyntaxOff

\pedef\foo{\textit{\doexpand\arabic{mycount}}}

\show\foo

This outputs

> \foo=\long macro:
->\textit {42}.
Related Question