マクロツイーター

はてダから移行した記事の表示が崩れてますが、そのうちに直せればいいのに(えっ)

あなたの展開力、大丈夫ですか? (2)

(前回の続き)
\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}%
}
で、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′〉}
となる。

この問題が解けた人は、自分を「展開芸人」と称しても差し支えないであろう。