補足1: 普通に実行される時
「保護」の機構は飽くまで「保護付完全展開」の時に意味をもつものなので、「普通に実行される時」、すなわち展開限定でない文脈ではマクロの動作に影響を与えない設計になっている。すなわち、展開限定文脈外では:
\protect
は\relax
に等置されている。\DeclareRobustCommand
で定義したマクロは、同じ定義本体で\newcommand
で定義したマクロと同じ動作を行う。
つまり、展開限定文脈外で \protect
の入った \NabeAzzLike
を
\setcoutner{enumi}{42} \NabeAzzLike{enumi}
のように使用すると、\protect
のない場合と全く同じ動作をする。
ただし、このことは、「展開限定文脈外」と「展開限定文脈で保護付完全展開が行われた場合」でマクロが同じ動作を行うことを自動的に保証するものではない。例として次の(不完全な)\NabeAzzLike
の定義を考えよう。
\def\NabeAzzLike#1{\protect\nabeazz{\arabic{#1}}}
保護付完全展開が入った場合は、\nabeazz
が展開されないので、先に \arabic
が展開されることになり、結果的に後で \nabeazz
が実行される時にはその引数は(規定通り)10 進表記になっている。ところが、保護付完全展開が入らずに直接実行される場合は、\nabeazz
の引数が \arabic{...}
のままになってしまってこれでは正常に動作しない。すなわち、このマクロでは、保護付完全展開が入る時と入らない時で動作が異なっている。
補足2: \protected@edef
LaTeX において、「保護付完全展開」の最も典型的な実装が \protected@edef
という内部命令である。この命令は \edef
と同じ構文をとる((ただしプリミティブでなくマクロなので、\global
等の接頭辞プリミティブを付けられない。\global
付き(つまり \xdef
)に相当するものとして \protected@xdef
が用意されている。))が、本体を「完全展開」する代わりに「保護付完全展開」する点が異なる。この \protected@edef
を用いて「保護付完全展開」の結果を確認することができる。((\protected@edef
の展開では \protect
を付けたままにしている。\protected@edef
の展開が複数回行われた場合に保護したものが結局展開されてしまうのを防ぐためである。))
\makeatletter \def\NabeAzzLike#1{% \expandafter\protect\expandafter\nabeazz\expandafter{\number\csname c@#1\endcsname}} \setcounter{enumi}{42} \protected@edef\result{\NabeAzzLike{enumi}} \show\result %==> \protect \nabeazz {42}
また、(展開可能なトークンを含む)トークン列を \typeout
で画面に表示させるときに行われる展開も実は「保護付完全展開」になっている。((中で \protected@write
という内部命令(つまり保護付の \write
)が使われている。))
\typeoput{\NabeAzzLike{enumi}} %==>「\nabeazz{42}」と出力
補足3: 頑強と完全展開可能は違う
「頑強」とは保護付完全展開、つまり「保護されたトークンは展開しない完全展開」を施しても正しく動くということである。従って、\edef
等を用いて(保護付でない)完全展開を行ってしまうと、保護されたトークンも展開されてしまうので、もはや正しく動く保証はない。完全展開しても正しく動くためには(文字通り)「完全展開可能」でなければならない。
完全展開可能でない処理を中に含むマクロは決して完全展開可能にはならない。ところが、頑強でない(脆弱な)マクロは「保護」することで容易に頑強にすることができる。*1これが、LaTeX でわざわざ「保護付完全展開」や「頑強」という概念が導入された理由であろう。
補足4: e-TeX 拡張のエンジンレベルでの保護
についてはまた今度。
*1:前回に述べたような微妙な問題はあるが。