macros

Expandieren von Argumenten vor dem Makroaufruf

Ich habe mir seit Tagen den Kopf darüber zerbrochen.Ich habe ein Makro,das einen Makronamen und seine Argumente entgegennimmt.Es ordnet dann die Argumente ein wenig um und ruft dann das übergebene Makro mit den neu angeordneten Argumenten auf und endet dann so:

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

wobei arga ... \argc die verarbeiteten Argumente sind. Jedoch. Ich muss \arga ... \argc vollständig erweitert haben, bevor das in #1 gespeicherte Makro aufgerufen wird. Ich kann das nicht für mein ganzes Leben herausfinden, nachdem ich tagelang mit \expandafter , \noexpand , etextools usw. gespielt habe. Ich kann expl3 nicht verwenden und ich würde es wirklich vorziehen, etextools nicht zu verwenden etextools aber etoolbox ist verfügbar. Hier ist ein 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}

Dies führt zu "\arga \argb \argc", aber ich möchte "arg1arg2arg3". \expandafter wird dies in \x tun, aber nicht für drei Argumente hintereinander. etextools hat einige Makros, um dies zu tun, aber ich möchte es wirklich vermeiden (es kollidiert in gewisser Weise mit etoolbox und ich muss etoolbox haben ). Ich konnte die etextools - Makros nicht zum Laufen bringen, selbst wenn ich es versuchte ( \ExpandNextTwo etc.)

UPDATE:Ich habe festgestellt,dass in meinem Fall die Args robuste Makros wie enthalten können:

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

In diesem Fall (mit egreg's Antwort als Beispiel)ist es nicht vollständig expandiert.Wie Joseph und egreg weiter unten erwähnen,ist das nicht machbar,man muss in solchen Fällen einfach nicht-robuste Makros verwenden,zum Beispiel.Ich werde die Frage so stehen lassen,weil sie informativ ist.

Der 'klassische' Ansatz ist die Verwendung von \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}

wo wir so viele von ihnen brauchen, um arg3 , dann arg2 und schließlich arg1 zu erweitern . (Dies ist effektiv in \ expl3 \exp_args:Nooo ) .

Die Regel für die Anzahl der \expandafter s ist 2 n – 1, wobei n die Anzahl der Token ist, die wir erweitern möchten. Für ein Token irgendwo voraus brauchen wir also nur ein \expandafter an jeder Stelle, um 'übersprungen' zu werden, um zwei Token zu erweitern (das zweite dann das erste) brauchen wir drei \expandafter s, für drei Token (wie im aktuellen Fall ) brauchen wir sieben \expandafter s und so eins. Dies ist am einfachsten zu sehen, wenn Sie eine kurze Sekunde schreiben/ausdrucken und die Befehle so durchstreichen, wie TeX sie lesen würde: Sie werden feststellen, dass alles funktioniert.

Wenn e-TeX verfügbar ist, können wir \edef und \unexpanded verwenden :

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

(Sie können dasselbe ohne e-TeX mit einer Reihe von Toks tun, aber das wird etwas verwirrend, also würde ich es normalerweise nicht tun.)


Die Frage sagt nein expl3 , aber im Gegensatz dazu würde der Ansatz mit einem Minimum der bereitgestellten Funktionen lauten

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

was hoffentlich viel besser lesbar ist. (Ich würde wahrscheinlich \exp_args:NVVV verwenden wollen, da wir 'in einer Variablen gespeicherter Wert' verwenden, aber diese Funktion ist nicht vordefiniert, also habe ich sie hier vermieden.)




Wenn Sie wirklich wollen, dass die Argumente vollständig erweitert werden, dann

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

führt zum Ausdrucken

arg1arg2arg3This is foo

wohingegen die auf \expandafter basierenden Lösungen drucken würden

arg1arg2arg\foo