Obtener definiciones de \let desde dentro de un grupo, dentro de un bucle

Obtener definiciones de \let desde dentro de un grupo, dentro de un bucle

Tengo la siguiente situación de bucle anidado:

\begingroup
  \def\do##1{%
    \begingroup
      \def\do####1{%
         \csletcs{somemacro@##1@####1}{someothermacro@##1@####1}}%
      \dolistloop\somelista
    \endgroup}%
  \dolistloop\somelistb
\endgroup

donde necesito que la \csletcsdefinición exista fuera de los dos grupos peronoglobalmente. Hay un buen truco de Martin Scharrer en un comentario a esta pregunta:

¿Cómo obtengo un valor de un grupo?

pero no funciona en un bucle como este, ya que poner la \endgroups en el bucle interno realmente arruina las siguientes iteraciones del bucle. ¿Hay alguna forma (etoolbox está bien) de obtener las \csletcsdefiniciones de los grupos sin romper más iteraciones de los bucles? Supongo que necesito los grupos; de lo contrario, los argumentos del bucle do no hacen referencia correctamente.

Para completar, aquí hay un intento de solución utilizando el truco de Martin Sharrer:

\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

Esto funciona para la primera iteración anidada y el cs resultante se define correctamente fuera de los grupos. Desafortunadamente, los grupos se cierran y las siguientes iteraciones son un verdadero desastre.

Respuesta1

Su ejemplo está un poco incompleto (tuve que hacer algunos cambios para que se compilara), pero la esencia de la respuesta es simplemente recopilar sus definiciones en una lista de tokens (configurada globalmente) y luego expandir la lista después del segundo grupo ( provocando definiciones locales).

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

Da: "macro indefinida:->a" como salida tipográfica.

Respuesta2

Puede usar cualquier controlador que desee para procesar una lista usando \forlistloopen lugar de \dolistloop; por lo que no es necesario redefinir \doen un grupo para no alterar la definición del bucle externo: simplemente use dos controladores diferentes.

\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

La parte relevante del archivo de registro:

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

?

información relacionada