Получение определений \let изнутри группы, внутри цикла

Получение определений \let изнутри группы, внутри цикла

У меня следующая ситуация с вложенным циклом:

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

где мне нужно, чтобы \csletcsопределение существовало вне двух групп, нонетглобально. Есть хороший трюк от Мартина Шаррера в комментарии к этому вопросу:

Как извлечь ценность из группы?

но это не работает в цикле, как этот, так как размещение \endgroups во внутреннем цикле действительно портит следующие итерации цикла. Есть ли способ (etoolbox подходит) вытащить определения \csletcsиз групп, не прерывая дальнейшие итерации циклов? Я предполагаю, что мне нужны группы, иначе аргументы цикла do не будут ссылаться должным образом.

Для полноты картины приведем попытку решения с использованием трюка Мартина Шаррера:

\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

Это работает для первой вложенной итерации, и результирующий cs определяется правильно вне групп. К сожалению, затем группы закрываются, и следующие итерации — это настоящий беспорядок.

решение1

Ваш пример немного неполный (мне пришлось внести некоторые изменения, чтобы скомпилировать его), но суть ответа заключается в том, чтобы просто собрать ваши определения в список токенов (задать глобально), а затем расширить список после второй группы (вызвав локальные определения).

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

Выдает: «неопределенный макрос:->a» в качестве набранного вывода.

решение2

Вы можете использовать любой обработчик для обработки списка, используя \forlistloopвместо \dolistloop; поэтому вам не нужно переопределять \doгруппу, чтобы не затирать определение внешнего цикла: просто используйте два разных обработчика.

\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

Соответствующая часть файла журнала:

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

?

Связанный контент