Expanding arguments before macro call

The 'classical' approach is to use \expandafter

\documentclass{article}
\begin{document}

\def\x#1#2#3#4{%
  \def\arga{#2}%
  \def\argb{#3}%
  \def\argc{#4}%
  \expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter#1%
    \expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter
      {\expandafter\expandafter\expandafter\arga\expandafter\expandafter\expandafter}%
        \expandafter\expandafter\expandafter{\expandafter\argb\expandafter}\expandafter
          {\argc}}

\def\y#1#2#3{\detokenize{#1#2#3}}

\x\y{arg1}{arg2}{arg3}

\end{document}

where we need so many of them to expand arg3 then arg2 and finally arg1. (This is what is effectively wrapped up in expl3's \exp_args:Nooo).

The rule of the number of \expandafters we need is 2n – 1, where n is how many tokens we want to expand. So for one token somewhere ahead, we need just one \expandafter in each place to be 'skipped', to expand two tokens (second one then the first one) we need three \expandafters, for three tokens (as in the current case) we need seven \expandafters, and so one. This is easiest to see if you write/print out a short second and cross off the commands as TeX would read them: you'll find everything works out.

With e-TeX available, we can use an \edef and \unexpanded:

\documentclass{article}
\begin{document}

\def\x#1#2#3#4{%
  \def\arga{#2}%
  \def\argb{#3}%
  \def\argc{#4}%
  \begingroup
    \edef\x{%
      \endgroup
      \noexpand#1
        {\unexpanded\expandafter{\arga}}%
        {\unexpanded\expandafter{\argb}}%
        {\unexpanded\expandafter{\argc}}%
    }%
  \x
}    

\def\y#1#2#3{\detokenize{#1#2#3}}

\x\y{arg1}{arg2}{arg3}

\end{document}

(You can do the same without e-TeX using a series of toks, but that gets a bit confusing so I'd not normally do it.)


The question says no expl3, but for contrast the approach using a minimium of the functions it provides would read

\documentclass{article}
\usepackage{expl3}
\begin{document}
\ExplSyntaxOn
\def\x#1#2#3#4{
  \def\arga{#2}
  \def\argb{#3}
  \def\argc{#4}
  \exp_args:Nooo#1\arga\argb\argc
}    
\ExplSyntaxOff
\def\y#1#2#3{\detokenize{#1#2#3}}

\x\y{arg1}{arg2}{arg3}

\end{document}

which is I hope a lot more readable. (I'd probably want to use \exp_args:NVVV as we are using 'value stored in a variable', but that function is not pre-defined so I've avoided it here.)


If you really want the arguments to be fully expanded, then

\documentclass{article}
\begin{document}

\def\x#1#2#3#4{%
  \begingroup\edef\z{\endgroup\noexpand#1{#2}{#3}{#4}}\z
}

\def\y#1#2#3{\detokenize{#1#2#3}}

\def\foo{This is foo}

\texttt{\x\y{arg1}{arg2}{arg3\foo}}

\end{document}

will result in printing

arg1arg2arg3This is foo

whereas the \expandafter based solutions would print

arg1arg2arg\foo