(前回の続き)
\def\withthreeargsexpanded#1#2#3#4{% \expandafter\def\expandafter\xx@arg@ii\expandafter{\expandafter{#2}}% \expandafter\def\expandafter\xx@arg@iii\expandafter{\expandafter{#3}}% \expandafter\def\expandafter\xx@arg@iv\expandafter{\expandafter{#4}}% \expandafter\expandafter\expandafter\expandafter \expandafter\expandafter\expandafter#1% \expandafter\expandafter\expandafter\xx@arg@ii \expandafter\xx@arg@iii \xx@arg@iv}
\newtoks\xx@arg@II \newtoks\xx@arg@III \newtoks\xx@arg@IV \def\withthreeargsexpandedii#1#2#3#4{% \xx@arg@II\expandafter{#2}% \xx@arg@III\expandafter{#3}% \xx@arg@IV\expandafter{#4}% \edef\xx@final{\noexpand#1{\the\xx@arg@II}{\the\xx@arg@III}{\the\xx@arg@IV}}% \xx@final}
\newtoks\xx@arg@II \newtoks\xx@arg@III \newtoks\xx@arg@IV \def\xx@assign@toks#1#2{#1\expandafter{#2}} \def\withthreeargsexpandedii#1#2#3#4{% \xx@assign@toks\xx@arg@II{#2}% \xx@assign@toks\xx@arg@III{#3}% \xx@assign@toks\xx@arg@IV{#4}% \edef\xx@final{\noexpand#1{\the\xx@arg@II}{\the\xx@arg@III}{\the\xx@arg@IV}}% \xx@final}
\usepackage{multiexpand} \def\withthreeargsexpanded#1#2#3#4{% \def\xx@i{#2}\def\xx@ii{#3}\def\xx@iii{#4}% \MultiExpandAfter{4}#1% \MultiExpandAfter{4}{% \MultiExpandAfter{4}\xx@i \MultiExpandAfter{4}}% \MultiExpandAfter{4}{% \MultiExpandAfter{2}\xx@ii \MultiExpandAfter{2}}% \MultiExpandAfter{2}{\xx@iii}% }
- 参考:multiexpand パッケージ(CTAN)
で、ZRさんの“模範解答”は?
私が一番無難だと思ってるのは次のコード。
\def\withthreeargsexpanded#1#2#3#4{% \edef\xx@next{\noexpand#1{\unexpanded\expandafter{#2}}% {\unexpanded\expandafter{#3}}{\unexpanded\expandafter{#4}}}% \xx@next }
この中に出現する
\unexpanded\expandafter{XXX}
は、(\edef
中において)「トークン列 XXX
を一度だけ展開したもの」を表している。etoolbox パッケージを利用すると、この部分を \expandonce{XXX}
と書くことができる。これを使うと、次のような非常に直接的で解りやすいコードが書ける。
\usepackage{etoolbox} \def\withthreeargsexpanded#1#2#3#4{% \edef\xx@next{\noexpand#1{\expandonce{#2}}{\expandonce{#3}}{\expandonce{#4}}}% \xx@next }
もし、「e-TeX 拡張を使わない」という条件であるならば、次のようにする。hak7a3 さんの 2 番目の解答と同じようにトークン列レジスタを利用するが、新たに \newtoks
で確保するのでなくてスクラッチを利用している。
\def\withthreeargsexpanded#1#2#3#4{% \begingroup \toks0\expandafter{#2}\toks2\expandafter{#3}\toks4\expandafter{#4}% \xdef\xx@next{\noexpand#1{\the\toks0}{\the\toks2}{\the\toks4}}% \endgroup \xx@next }
番外1
これが一番簡単!!
\usepackage{expl3} \ExplSyntaxOn \cs_set_eq:NN \withthreeargsexpanded \exp_args:Nooo \ExplSyntaxOff
番外2
発展課題
これで、件の問題の解説を終えることにする。「展開」に関する問題としては非常に基礎的なものであったので、“TeX な人”の中には、「こんな問題は簡単すぎて考える気すら起きない」という人もいたであろう。そういうわけで、発展課題として、例の制約を加えたものを出題しておこう。
完全展開可能にしてみよう。
そう、ソレである。要件を正確に述べると以下のようになる。
\CS
を任意の制御綴とする。また、〈A〉、〈B〉、〈C〉を任意のトークン列とし、各々を一回展開したトークン列を〈A′〉、〈B′〉、〈C′〉とする。この時、\withthreeargsexpanded\CS{
〈A〉}{〈B〉}{〈C〉}
を何回か展開した結果が
\CS{
〈A′〉}{〈B′〉}{〈C′〉}
となる。
この問題が解けた人は、自分を「展開芸人」と称しても差し支えないであろう。