
다음과 같은 중첩 루프 상황이 있습니다.
\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를 넣으면 다음 루프 반복이 실제로 엉망이 되기 때문에 이와 같은 루프에서는 작동하지 않습니다 . \csletcs
루프의 추가 반복을 중단하지 않고 그룹에서 정의를 가져올 수 있는 방법이 있습니까(etoolbox는 괜찮습니까) ? 그룹이 필요하다고 가정합니다. 그렇지 않으면 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
?