macros

매크로 호출 전 인수 확장

나는 며칠 동안 이것에 대해 머리를 강타했습니다. 매크로 이름과 해당 인수를 사용하는 매크로가 있습니다. 그런 다음 인수를 약간 재정렬한 다음 재정렬된 인수로 전달된 매크로를 호출하여 다음과 같이 끝납니다.

#1{\arga}{\argb}{\argc}

여기서 arga ... \argc 는 처리된 인수입니다. 하지만. #1 에 저장된 매크로 가 호출 되기 전에 \arga ... \argc 가 완전히 확장 되어야 합니다. \expandafter , \noexpand , etextools 등 을 가지고 놀고 난 후에 이것을 해결할 수 없습니다. 나는 expl3 을 사용할 수 없으며 etoolbox 를 사용하지 않는 것을 정말로 선호 하지만 etextools 를 사용할 수 있습니다. 다음은 MWE입니다.

\documentclass{article}
\begin{document}

\def\x#1#2#3#4{%
  \def\arga{#2}%
  \def\argb{#3}%
  \def\argc{#4}%
  #1{\arga}{\argb}{\argc}}

\def\y#1#2#3{\detokenize{#1#2#3}}

\x\y{arg1}{arg2}{arg3}

\end{document}

결과는 "\arga \argb \argc"이지만 "arg1arg2arg3"이 필요합니다. \expandafter\x 에서 이것을 수행 하지만 연속된 세 개의 인수에 대해서는 수행하지 않습니다. etextools 에는 이를 수행하는 몇 가지 매크로가 있지만 정말 피하고 싶습니다(어떤 면에서 etoolbox와 충돌하며 etoolbox 가 있어야 etoolbox ). \ExpandNextTwo 등) etextools 매크로가 작동하도록 할 수 없습니다 .

업데이트: 제 경우에는 args에 다음과 같은 강력한 매크로가 포함될 수 있다는 것을 깨달았습니다.

\documentclass{article}
\usepackage{etoolbox}
\begin{document}

\def\x#1#2#3#4{%
  \def\arga{#2}%
  \edef\argb{\ifstrequal{#3}{arg2}{arg2}{}}%
  \def\argc{#4}%
  {\protected\z{\noexpand#1{\arga}{\argb}{\argc}}\z}}

\def\y#1#2#3{\detokenize{#1#2#3}}

\x\y{arg1}{arg2}{arg3}

\end{document}

이 경우(예로 egreg의 답변 사용) 완전히 확장되지 않습니다. Joseph과 egreg가 아래에서 언급한 것처럼 이것은 불가능합니다. 예를 들어 이러한 경우에는 강력하지 않은 매크로를 사용해야 합니다. 유익한 정보이기 때문에 질문을 그대로 두겠습니다.

'고전적인' 접근 방식은 \expandafter 를 사용하는 것입니다.

\documentclass{article}
\begin{document}

\def\x#1#2#3#4{%
  \def\arga{#2}%
  \def\argb{#3}%
  \def\argc{#4}%
  \expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter#1%
    \expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter
      {\expandafter\expandafter\expandafter\arga\expandafter\expandafter\expandafter}%
        \expandafter\expandafter\expandafter{\expandafter\argb\expandafter}\expandafter
          {\argc}}

\def\y#1#2#3{\detokenize{#1#2#3}}

\x\y{arg1}{arg2}{arg3}

\end{document}

arg3 다음 arg2 그리고 마지막으로 arg1 을 확장하기 위해 많은 것들이 필요합니다 . (이것은 효과적으로 expl3\exp_args:Nooo Nooo 에 래핑된 것입니다 ).

\expandafter 수의 규칙 은 2 n – 1입니다. 여기서 n 은 확장하려는 토큰 수입니다. 따라서 앞으로 어딘가에 하나의 토큰 에 대해 '건너뛰기'할 각 위치에서 하나의 \expandafter 가 필요합니다.두 개의 토큰(두 번째 토큰 다음 첫 번째 토큰)을 확장하려면 세 개의 토큰에 대해 세 개의 \expandafter 가 필요 합니다(현재의 경우와 같이 ) 우리는 7개의 \expandafter 가 필요 하고 그래서 1개가 필요합니다. 이것은 여러분이 짧은 초를 작성/출력하고 TeX이 읽을 때 명령에 줄을 긋는지 확인하는 가장 쉬운 방법입니다. 모든 것이 제대로 작동하는 것을 알게 될 것입니다.

e-TeX를 사용할 수 있으면 \edef\unexpanded 를 사용할 수 있습니다 .

\documentclass{article}
\begin{document}

\def\x#1#2#3#4{%
  \def\arga{#2}%
  \def\argb{#3}%
  \def\argc{#4}%
  \begingroup
    \edef\x{%
      \endgroup
      \noexpand#1
        {\unexpanded\expandafter{\arga}}%
        {\unexpanded\expandafter{\argb}}%
        {\unexpanded\expandafter{\argc}}%
    }%
  \x
}    

\def\y#1#2#3{\detokenize{#1#2#3}}

\x\y{arg1}{arg2}{arg3}

\end{document}

(일련의 톡을 사용하여 e-TeX 없이도 동일한 작업을 수행할 수 있지만 약간 혼란스러워서 일반적으로 하지 않습니다.)


질문은 no expl3 이라고 말하지만 대조적으로 제공하는 기능을 최소한으로 사용하는 접근 방식은 다음을 읽습니다.

\documentclass{article}
\usepackage{expl3}
\begin{document}
\ExplSyntaxOn
\def\x#1#2#3#4{
  \def\arga{#2}
  \def\argb{#3}
  \def\argc{#4}
  \exp_args:Nooo#1\arga\argb\argc
}    
\ExplSyntaxOff
\def\y#1#2#3{\detokenize{#1#2#3}}

\x\y{arg1}{arg2}{arg3}

\end{document}

그것은 훨씬 더 읽기를 바랍니다. (아마도 '변수에 저장된 값' 을 사용하기 때문에 \exp_args:NVVV 를 사용하고 싶지만 해당 함수는 미리 정의되어 있지 않으므로 여기서는 피했습니다.)




인수가 완전히 확장 되기를 정말로 원한다면

\documentclass{article}
\begin{document}

\def\x#1#2#3#4{%
  \begingroup\edef\z{\endgroup\noexpand#1{#2}{#3}{#4}}\z
}

\def\y#1#2#3{\detokenize{#1#2#3}}

\def\foo{This is foo}

\texttt{\x\y{arg1}{arg2}{arg3\foo}}

\end{document}

인쇄가 발생합니다

arg1arg2arg3This is foo

반면 \expandafter 기반 솔루션은

arg1arg2arg\foo