
我有以下嵌套循環情況:
\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
?