그룹 내부, 루프 내부에서 \let 정의 가져오기

그룹 내부, 루프 내부에서 \let 정의 가져오기

다음과 같은 중첩 루프 상황이 있습니다.

\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

?

관련 정보