在组内、循环内获取 \let 定义

在组内、循环内获取 \let 定义

我有以下嵌套循环的情况:

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

我需要让\csletcs定义存在于这两个组之外,但是不是全局范围内。Martin Scharrer 在对这个问题的评论中提出了一个很好的技巧:

如何从一个组中提取值?

但它在这样的循环中不起作用,因为将\endgroups 放在内部循环中确实会搞乱下一次循环迭代。有没有办法(etoolbox 可以)将定义\csletcs从组中取出而不中断循环的进一步迭代?我认为我需要这些组,否则 do 循环参数无法正确引用。

为了完整起见,这里尝试使用 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

这对于第一次嵌套迭代有效,并且生成的 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

?

相关内容