
Ich habe die folgende Situation mit verschachtelter Schleife:
\begingroup
\def\do##1{%
\begingroup
\def\do####1{%
\csletcs{somemacro@##1@####1}{someothermacro@##1@####1}}%
\dolistloop\somelista
\endgroup}%
\dolistloop\somelistb
\endgroup
wo ich die \csletcs
Definition außerhalb der beiden Gruppen haben muss, abernichtglobal. Es gibt einen netten Trick von Martin Scharrer in einem Kommentar zu dieser Frage:
Wie erhalte ich einen Wert aus einer Gruppe?
aber es funktioniert nicht in einer Schleife wie dieser, da das Einfügen des \endgroup
s in die innere Schleife die nächsten Schleifeniterationen wirklich durcheinander bringt. Gibt es eine Möglichkeit (etoolbox ist ok), die \csletcs
Definitionen aus den Gruppen zu holen, ohne weitere Iterationen der Schleifen zu unterbrechen? Ich gehe davon aus, dass ich die Gruppen brauche, da die Argumente der do-Schleife sonst nicht richtig referenziert werden.
Nur der Vollständigkeit halber hier ein Lösungsversuch mit Martin Sharrers Trick:
\begingroup
\def\do##1{%
\begingroup
\def\do####1{%
\edef\@z{\endgroup\endgroup\csletcs{somemacro@##1@####1}{someothermacro@##1@####1}}\@z}%
\dolistloop\somelista
\endgroup}%
\dolistloop\somelistb
\endgroup
Dies funktioniert für die erste verschachtelte Iteration und das resultierende cs ist außerhalb der Gruppen ordnungsgemäß definiert. Leider werden die Gruppen dann geschlossen und die nächsten Iterationen sind ein echtes Chaos.
Antwort1
Ihr Beispiel ist ein wenig unvollständig (ich musste einige Änderungen vornehmen, damit es kompiliert werden konnte), aber die Antwort besteht im Wesentlichen darin, Ihre Definitionen in einer Token-Liste zu sammeln (global festgelegt) und die Liste dann nach der zweiten Gruppe zu erweitern (was zu lokalen Definitionen führt).
\documentclass{article}
\usepackage{etoolbox}
\begin{document}
\makeatletter
\def\somelista{x}
\def\somelistb{y}
\texttt{\meaning\somemacro@y@x}
\def\someothermacro@y@x{a}
\begingroup
\def\do#1{%
\begingroup
\def\do##1{%
\global\toks1=\expandafter{\the\toks1 \csletcs{somemacro@#1@##1}{someothermacro@#1@##1}}}%
\dolistloop\somelista
\endgroup}%
\dolistloop\somelistb
\endgroup
\the\toks1
\texttt{\meaning\somemacro@y@x}
\makeatother
\end{document}
Ergibt: „undefined macro:->a“ als gesetzte Ausgabe.
Antwort2
Sie können zum Verarbeiten einer Liste jeden beliebigen Handler \forlistloop
anstelle von verwenden \dolistloop
. Sie müssen also in einer Gruppe nicht neu definieren, \do
um die äußere Schleifendefinition nicht zu beeinträchtigen: Verwenden Sie einfach zwei unterschiedliche Handler.
\documentclass{article}
\usepackage{etoolbox}
\newcommand\processlistb[1]{%
\def\temp{#1}%
\forlistloop\processlista\somelista
}
\newcommand\processlista[1]{%
\csletcs{somemacro@\temp @#1}{someothermacro@\temp @#1}%
\csshow{somemacro@\temp @#1}%
}
\listadd\somelista{a}
\listadd\somelista{b}
\listadd\somelista{c}
\listadd\somelistb{x}
\listadd\somelistb{y}
% Just to add some mock definitions
\csdef{someothermacro@x@a}{xa}
\csdef{someothermacro@x@b}{xb}
\csdef{someothermacro@x@c}{xc}
\csdef{someothermacro@y@a}{ya}
\csdef{someothermacro@y@b}{yb}
\csdef{someothermacro@y@c}{yc}
% Do the iterations
\forlistloop\processlistb\somelistb
\stop
Der relevante Teil der Protokolldatei:
> \somemacro@x@a=macro:
->xa.
<recently read> \somemacro@x@a
l.29 \forlistloop\processlistb\somelistb
?
> \somemacro@x@b=macro:
->xb.
<recently read> \somemacro@x@b
l.29 \forlistloop\processlistb\somelistb
?
> \somemacro@x@c=macro:
->xc.
<recently read> \somemacro@x@c
l.29 \forlistloop\processlistb\somelistb
?
> \somemacro@y@a=macro:
->ya.
<recently read> \somemacro@y@a
l.29 \forlistloop\processlistb\somelistb
?
> \somemacro@y@b=macro:
->yb.
<recently read> \somemacro@y@b
l.29 \forlistloop\processlistb\somelistb
?
> \somemacro@y@c=macro:
->yc.
<recently read> \somemacro@y@c
l.29 \forlistloop\processlistb\somelistb
?