macros

Expansão dos argumentos antes da chamada macro

Tenho batido com a minha cabeça contra isto durante dias.Tenho uma macro que leva um nome de macro e os seus argumentos.Depois reordena um pouco os argumentos e depois chama a macro passada de macro com os argumentos reordenados e termina assim:

#1{\arga}{\argb}{\argc}

onde arga ... \argc são os argumentos processados. No entanto. Eu preciso ter \arga ... \argc totalmente expandido antes que a macro armazenada em #1 seja chamada. Eu não consigo resolver isso depois de dias jogando com \expandafter , \noexpand , etextools etc. Eu não posso usar expl3 e eu realmente prefiro não usar etextools mas etoolbox está disponível. Aqui está um MWE:

\documentclass{article}
\begin{document}

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

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

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

\end{document}

Isso resulta em "\arga \argb \argc", mas eu quero "arg1arg2arg3". \expandafter fará isso em \x , mas não para três argumentos seguidos. etextools tem algumas macros para fazer isso, mas eu realmente quero evitá-lo (ele colide com etoolbox de algumas maneiras e eu devo ter etoolbox ). Não consegui fazer com que as macros etextools funcionassem mesmo quando tentei ( \ExpandNextTwo etc.)

ATUALIZAÇÃO:Percebi que no meu caso,as argolas podem conter macros robustas como:

\documentclass{article}
\usepackage{etoolbox}
\begin{document}

\def\x#1#2#3#4{%
  \def\arga{#2}%
  \edef\argb{\ifstrequal{#3}{arg2}{arg2}{}}%
  \def\argc{#4}%
  {\protected\z{\noexpand#1{\arga}{\argb}{\argc}}\z}}

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

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

\end{document}

Nesse caso (usando a resposta do egreg como exemplo),não está totalmente expandida.Como Joseph e egreg mencionam abaixo,isto não é exequível,basta utilizar macros não robustos em tais casos,por exemplo.Vou deixar a pergunta ficar como está porque é informativa.

A abordagem 'clássica' é usar \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}

onde precisamos de muitos deles para expandir arg3 , depois arg2 e finalmente arg1 . (Isto é o que está efetivamente encerrado no \ expl3 \exp_args:Nooo ) .

A regra do número de \expandafter s que precisamos é 2 n – 1, onde n é quantos tokens queremos expandir. Então, para um token em algum lugar à frente, precisamos apenas de um \expandafter em cada lugar para ser 'pulado', para expandir dois tokens (o segundo e o primeiro) precisamos de três \expandafter s, para três tokens (como no caso atual ) precisamos de sete \expandafter s, e assim um. Isso é mais fácil de ver se você escrever/imprimir um breve segundo e riscar os comandos como o TeX os leria: você descobrirá que tudo funciona.

Com o e-TeX disponível, podemos usar um \edef e \unexpanded 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}

(Você pode fazer o mesmo sem o e-TeX usando uma série de toks, mas isso fica um pouco confuso, então eu normalmente não faria isso.)


A pergunta não diz expl3 , mas por contraste a abordagem usando um mínimo das funções que ele fornece seria lida

\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}

que é espero muito mais legível. (Eu provavelmente gostaria de usar \exp_args:NVVV , pois estamos usando 'valor armazenado em uma variável', mas essa função não é pré-definida, então a evitei aqui.)




Se você realmente deseja que os argumentos sejam totalmente expandidos, então

\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}

resultará na impressão

arg1arg2arg3This is foo

enquanto as soluções baseadas \expandafter imprimiriam

arg1arg2arg\foo