
次のようなネストされたループ状況があります。
\begingroup
\def\do##1{%
\begingroup
\def\do####1{%
\csletcs{somemacro@##1@####1}{someothermacro@##1@####1}}%
\dolistloop\somelista
\endgroup}%
\dolistloop\somelistb
\endgroup
\csletcs
2つのグループの外に定義が存在する必要があるが、ないグローバルに。この質問に対するコメントに、Martin Scharrer からの素晴らしいトリックがあります。
しかし、このようなループでは動作しません。\endgroup
内側のループに s を入れると、次のループの反復が本当に混乱します。\csletcs
ループの反復を中断せずにグループから定義を取得する方法 (etoolbox は OK) はありますか? グループが必要だと思います。そうしないと、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
あなたの例は少し不完全です (コンパイルするためにいくつか変更を加える必要がありました) が、答えの要点は、定義をトークン リスト (グローバルに設定) に収集し、2 番目のグループの後にリストを展開する (ローカル定義が発生する) ことです。
\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}
タイプセット出力として「undefined macro:->a」が返されます。
答え2
\forlistloop
;の代わりに を使用して、リストを処理するための任意のハンドラーを使用できます\dolistloop
。そのため、外側のループ定義を破壊しないようにグループ内で再定義する必要はありません\do
。2 つの異なるハンドラーを使用するだけです。
\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
?