Abrufen von \let-Definitionen aus einer Gruppe, innerhalb einer Schleife

Abrufen von \let-Definitionen aus einer Gruppe, innerhalb einer Schleife

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 \csletcsDefinition 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 \endgroups in die innere Schleife die nächsten Schleifeniterationen wirklich durcheinander bringt. Gibt es eine Möglichkeit (etoolbox ist ok), die \csletcsDefinitionen 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 \forlistloopanstelle von verwenden \dolistloop. Sie müssen also in einer Gruppe nicht neu definieren, \doum 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

?

verwandte Informationen