理工系研究者のための Mac OS X, Windows, Linux メモ
 

\expandafter

作成日:2012/2/2

はじめに

\expandafterは展開の順序を制御するTeXのプリミティブ。このプリミティブの用法と使用例について紹介する。

説明や例の多くを下記の参考文献から引用している。

\expandafterについて

\expandafterは,2つ以上のトークンを従える。

\expandafter⟨token1⟩⟨token2⟩⟨token3⟩ ... ⟨tokenN⟩
TeXは\expandafterを読み込んだ後, 後置されている⟨token1⟩を読み込むが、 これを展開せずに保存した後、⟨token2⟩を読み込み展開する。 ⟨token2⟩の展開が終われば,⟨token1⟩をその前に置く。

\expandafterは2つ目のトークン⟨token2⟩が何かによって少しずつ異なる動きをする。

⟨token2⟩がマクロの場合

\expandafter⟨token1⟩\macro [⟨arguments⟩]

先ず\macroを展開する。 マクロに引数⟨arguments⟩がある場合にはそれらも読み込んでから展開する。 展開が終われば、\macroを展開したトークン列⟨expanded_macro⟩の前に保存したトークン⟨token1⟩を置く。

⟨token1⟩⟨some_tokens_from_\macro⟩
マクロは一段階しか展開しないことに注意。マクロの中にマクロがあってもそれはそのままになる。

⟨token2⟩がプリミティブの場合

プリミティブはそれ以上展開できないので、結局のところ\expandafterは何の役にも立たない。 ただし、いくつか例外があるので以下で紹介する。

⟨token2⟩がもう一つの\expandafterの場合

\expandafter⟨token1⟩\expandafter⟨token3⟩⟨token4⟩

もう一つの\expandafterはその次のトークン⟨token3⟩を保存し、 ⟨token4⟩を展開する。 この展開が終われば、まず保存していた⟨token3⟩を頭につけて、 さらに⟨token1⟩をそのさらに頭に付ける。

⟨token1⟩⟨token3⟩⟨some_tokens_from_token4⟩

そして、⟨token1⟩からまた展開を始めることになる。

⟨token2⟩が\csnameの場合

\expandafter⟨token1⟩\csname⟨some_tokens⟩\endcsname

\csnameから\endcsnameまで読み込み、これらに挟まれるトークンリストからなるコントロールシーケンスが作られる。例えば ⟨some_tokens⟩=hogeならば、

⟨token1⟩\hoge
が残る。

⟨token2⟩が\theの場合

\expandafter⟨token1⟩\the⟨register⟩

\theに続く⟨register⟩も読み込み、レジスタ値に展開し、 その前に⟨token1⟩を置く。

⟨token1⟩⟨some_tokens_from_register⟩

例1

\def\xx [#1]{The argument is #1.}
\def\yy{[ABC]}
として,
\xx\yy
を実行するとエラーになる。
! Use of \xx doesn't match its definition.
\lt;*\gt; \xx\yy
なぜならば,\xxの引数として与えられている\yyは展開されずに読み込まれるから。 \yyを展開したあとで読み込みたければ,\expandafterを用いればよい。
\expandafter\xx\yy
次に,マクロがもう一段深い場合にはどうなるだろうか。
\def\zz{\yy}
のように\zzが定義されているとき,
\expandafter\xx\zz
はうまく働くだろうか。この場合もエラーとなる。
! Use of \xx doesn't match its definition.
\zz ->\yy
なぜならば,\zz\yyには展開されるが,展開がそこで終わってしまうから。 最後まで展開させるには,\edefを用いると良い。
\edef\zz{\yy}
今度はうまくいく。
\expandafter\xx\zz

例2

3つのマクロ\a, \b, \cがあるとする。 この3つのマクロを

\a \b \c
の順に並べて,逆順に展開したいとする。つまり、\cを展開し,次に\bを展開し,最後に\aを展開したいとする。

表現が短くするために

\let\ex = \expandafter
としておく。

上記の展開を実現するには

\ex_1 \ex_2 \ex_3 \a \ex_4 \b \c
とするとよい。\exの添え字は便宜上付けているだけで実際には\exに等しいとする。

これを実行すると,まず\ex_1が実行され,\ex_2が保存される。 そして実行が\ex_3に移る。

\ex_3は次の\aを保存し,\ex_4を実行する。

\ex_4\bを保存し,\cを展開する。 これでまずは\cが展開された。

逆に戻って,保存していた\b\cを展開したものの前に置く。 さらに保存していた\a\bの前に置く。さらに保存していた\ex_2\aの前に置く。

保存していたものをすべてはき出したので,\ex_2を実行する。

\ex_2は次の\aを保存して,\bを読み込み展開する。\bの展開が終わればその前に\aを置く。そして最後に\aを展開して終了する。

\ex_1 \ex_2 \ex_3 \a \ex_4 \b \c
→\ex_2 \a \b ⟨tokens_from_\c⟩
→\a ⟨tokens_from_\b⟩ ⟨tokens_from_\c⟩
→⟨tokens_from_\a⟩ ⟨tokens_from_\b⟩ ⟨tokens_from_\c⟩

例3

コントロール・シーケンスには\から始まりカテゴリコード12の文字(英小文字,英大文字)しかつかえないことになっているが,\csname, \endcsnameを用いれば,数字入りのコントロールシーケンスを作成することも可能になる。例えば

\csname a?a-4\endcsname
\a?a-4 というコントロールシーケンスを表している。 数字やクエスチョンマークまで加えることが出来る。

このコントロールシーケンスを定義するには,

\expandafter\def\csname a?a-4\endcsname{Peculiar control sequence.}
とすればよい。\expandafter\defを保存して,\csname ... \endcsnameを先に実行し,コントロールシーケンスを生成した後,その前に\defを配置する。

ここで作った特殊なコントロールシーケンスを使うときには,\csnameを使って,

\expandafter\show\csname a?a-4\endcsname
のように書けばよい。

参考サイト・参考文献