我有以下嵌套循环的情况:
\begingroup
\def\do##1{%
\begingroup
\def\do####1{%
\csletcs{somemacro@##1@####1}{someothermacro@##1@####1}}%
\dolistloop\somelista
\endgroup}%
\dolistloop\somelistb
\endgroup
我需要让\csletcs
定义存在于这两个组之外,但是不是全局范围内。Martin Scharrer 在对这个问题的评论中提出了一个很好的技巧:
但它在这样的循环中不起作用,因为将\endgroup
s 放在内部循环中确实会搞乱下一次循环迭代。有没有办法(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
?