ループ内のグループ内から \let 定義を取得する

ループ内のグループ内から \let 定義を取得する

次のようなネストされたループ状況があります。

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

\csletcs2つのグループの外に定義が存在する必要があるが、ないグローバルに。この質問に対するコメントに、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

?

関連情報