マクロツイーター

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

きょうの e-TeX (3): \unexpanded

  • \unexpanded{<トークン>...} :[展開可能] \edef 中で用いた場合、中身の <トークン>... に展開され、しかもそれ以上展開されない。

\edef 中で「この部分だけは展開されて欲しくない」ということはよくある。この場合、\noexpand を使うと、直後のトークンの展開を抑止することができるが、(特に可変な)トークン列に対して「この部分は展開させたくない」という場合には \noexpand では対応しきれないので、そういう時に有用である。

ただし、非 e-TeX でも、「\edef 中でトークレジスタの参照(\the\toks...)はその中身に展開された後はそれ以上は展開されない」という性質を使って今述べたような処理を実現できる場合がある。

例えば、引数のないマクロに対して、その置換テキストの前後に好きなトークン列を追加するという機能をもつマクロ \enclose を作りたいとする。\unexpanded を用いて次のように非常に明快に実装できる。


%% \enclose\CS{<前>}{<後>}
% マクロ \CS を <前><現在の置換テキスト><後> に再定義する。
\def\enclose#1#2#3{%
\edef#1{\unexpanded{#2}\onceexpand{#1}\unexpanded{#3}}}
% (\edef 中で)マクロ #1 を「一度だけ」展開する
\def\onceexpand#1{\expandafter\unexpanded\expandafter{#1}}
[2013-05-15訂正]\enclose の定義の括弧が不足しているのと制御綴名が誤っているのを修正。

一方、非 e-TeX でも次のようにトークレジスタを用いれば実装は可能である。


\def\enclose#1#2#3{%
% \toks0 の代入の局所化の処理は省略した
\toks0{#2}\toks2\expandafter{#1}\toks4{#3}%
\edef#1{\the\toks0 \the\toks2 \the\toks4 }}
[2013-05-15訂正]最終行の \toks の前の \the が(全部)抜けていたのを修正した。

しかし途中で代入を行う必要のない \unexpanded の方が使える場面が多いと思われる。ちなみに、上の例に現れたマクロ \onceexpand は etoolbox パッケージで提供される命令にも含まれている。

なお、\edef 等の外(代入・実行が行われる状況)に \unexpanded{...} が現れた場合は、その中身に展開された後、中身に対する展開が行われる。つまり、\unexpanded{...} がないのと同じである。この辺りの仕様は実はトークレジスタの参照と全く同じになっていて、\noexpand の仕様とは異なる。