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 \expandafter
s 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 \expandafter
s, for three tokens (as in the current case) we need seven \expandafter
s, 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