# Expanding all arguments of a command before appending it to another macro

\documentclass{article}
\makeatletter
\usepackage{ltxcmds}

\newcounter{mycounter}
\setcounter{mycounter}{7}

\newcommand{\mysndc}[3]{#1 #2 #3}

\newcommand{\mycommand}{}

\newcommand{\mytrdc}[1]{\ltx@GlobalAppendToMacro{\mycommand}{%
\mysndc{\arabic{mycounter}}{#1}{\thepage}}}

\makeatother
\begin{document}
x

\mytrdc{8}

\newpage
\setcounter{mycounter}{4}

\mycommand
\end{document}


When \mycommand is called, it is \mysndc{\arabic{mycounter}}{8}{\thepage} resulting in 4 8 2. What I would like it to be is \mysndc{7}{8}{2} resulting in 7 8 1. To achieve this, the arguments of \mysndc must be expanded before \mysndc is appended to \mycommand. \expandafter should be useful, but diverse placements of it (also more than one \expandafter) did not yield the desired result, e.g.

\newcommand{\mytrdc}[1]{\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\ltx@GlobalAppendToMacro{\mycommand\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter}{\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\mysndc\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter{\expandafter\expandafter\expandafter\arabic{mycounter}\expandafter\expandafter\expandafter}\expandafter\expandafter\expandafter{\expandafter#1\expandafter}\expandafter{\thepage}}}


. Where must I place how many \expandafters to expand the arguments of \mysndc before appending it to \mycommand and why exactly? I found numerous similar questions and answers to them here at tex.SE, but still was not able to get it right. If possible, I prefer a solution with expandafters, so that I can learn from it, and without using e-TeX/etextools/etextoolbox/LaTeX3/...

• Can you be sure that the arguments are all expandable? If so, does your macro itself need to be expandable? To what extent are we allowed to make assumptions about the input? Can we use e-TeX? Jan 26 '14 at 16:29
• @JosephWright: \arabic{mycounter}, 8, \thepage should all be expandable, but I would prefer an e-TeX-free solution. Jan 26 '14 at 16:33

## 2 Answers

The easiest way to tackle this is probably to force expansion of everything using \edef, as that was we avoid needing to shuffle arguments. (\mytrdc is not expandable in any case, so we can use an assignment.) One possible approach using \edef:

\documentclass{article}

\usepackage{ltxcmds}

\newcounter{mycounter}
\setcounter{mycounter}{7}

\newcommand{\mysndc}[3]{#1 #2 #3}

\newcommand{\mycommand}{}
\makeatletter
\newcommand{\mytrdc}[1]{%
\begingroup
\edef\x{%
\endgroup
\noexpand\ltx@GlobalAppendToMacro{\noexpand\mycommand}{%
\noexpand\mysndc{\arabic{mycounter}}{#1}{\thepage}}}%
\x}

\makeatother
\begin{document}
x

\mytrdc{8}

\newpage
\setcounter{mycounter}{4}

\show\mycommand
\end{document}


The idea is simple: create a temporary, \edefed macro \x which contains the expanded material required plus the necessary 'set up', then execute it. Everything is done in a group so we don't mess up any other meaning of \x.

• I'm taking it we don't have a full description of the expandability of the arguments beyond the fact that they are expandable. (Number of expansion steps required is not fixed.) Jan 26 '14 at 16:39
• Instead of expanding something you expand everything but \noexpand those things that shall not be expanded? Clever! Jan 26 '14 at 16:46
• @Stephen Yes: working on the basis that we don't have to use \expandafter as your overall aim involves an assignment anyway, I took the easiest approach for forcing expansion. Jan 26 '14 at 16:47

You could do it with \expandafter, but it would be really long, as passing from \arabic{mycounter} to 7 requires four steps of expansion:

\arabic{mycounter}
\expandafter \@arabic \csname c@mycounter\endcsname
\@arabic \c@mycounter
\number \c@mycounter
7


Expanding \thepage requires one step more, because the first level expansion is \arabic{page}.

Let's see it in a simpler case. You have

\newcommand{\mymacro}[1]{\dosomething{#1}}


where \dosomething is your “append” macro, where you want that #1 is the “final” result after expansion of the argument. So, if you have

\def\foo{A}


you want that \dosomething is fed with A, rather than with \foo. This is easy:

\expandafter\mymacro\expandafter{\foo}


If instead you have

\def\foo{\baz}\def\baz{A}


you need to expand \foo twice:

\expandafter\expandafter\expandafter\mymacro
\expandafter\expandafter\expandafter{\foo}


In general, if you want n expansions, you need 2n–1 \expandafter tokens. In the case of \arabic{mycounter} you'd need 15 before and after \mymacro. For \thepage they would be 31. But the affair is complicated by having three arguments!

So a different approach is needed. The simplest one is to use \edef or, in case your arguments can contain “dangerous” things such as \textbf, with \protected@edef; I'll do it slightly differently from Joseph's answer, just for fun.

\documentclass{article}

\usepackage{etoolbox}

\newcounter{mycounter}
\setcounter{mycounter}{7}

\newcommand{\mysndc}[3]{#1 #2 #3}

\newcommand{\mycommand}{}

\makeatletter
\newcommand{\mytrdc}[1]{%
\begingroup
\protected@edef\x{{\arabic{mycounter}}{#1}{\thepage}}%
\expandafter\endgroup
\expandafter\gappto\expandafter\mycommand\expandafter
{\expandafter\mysndc\x}%
}

\makeatother
\begin{document}
x

\mytrdc{8}

\newpage
\setcounter{mycounter}{4}

\texttt{\meaning\mycommand}
\end{document}


The \x temporary macro will expand to {7}{8}{1} and it will disappear as soon as the chain of \expandafter's is performed (the group will be ended after \x has been expanded.

Here's a different approach, with LaTeX3.

\documentclass{article}
\usepackage{xparse}

\newcounter{mycounter}
\newcommand{\mysndc}[3]{#1 #2 #3}

\ExplSyntaxOn
\NewDocumentCommand{\mytrdc}{ m }
{
\stephen_mytrdc:n { #1 }
}
\NewDocumentCommand{\mycommand}{ }
{
\tl_use:N \g_stephen_list_tl
}

\tl_new:N \g_stephen_list_tl

\cs_new_protected:Npn \stephen_mytrdc:n #1
{
\stephen_appto_mycommand:ffn { \arabic{mycounter} } { \thepage } { #1 }
}

\cs_new_protected:Npn \stephen_appto_mycommand:nnn #1 #2 #3
{
\tl_gput_right:Nn \g_stephen_list_tl { \mysndc { #1 } { #3 } { #2 } }
}
\cs_generate_variant:Nn \stephen_appto_mycommand:nnn { ff }
\ExplSyntaxOff

\begin{document}
\setcounter{mycounter}{7}

x

\mytrdc{8}

\newpage
\setcounter{mycounter}{4}
y

\mytrdc{42}

\expandafter\show\csname g_stephen_list_tl\endcsname
\end{document}


In a real document you'd use \mycommand instead of \show. The double inversion of the arguments is for efficiency. The output on the terminal will be

> \g_stephen_list_tl=macro:
->\mysndc {7}{8}{1}\mysndc {4}{42}{2}.