\defの修飾子

TeXでマクロを定義するには\defを使います.しかし,この\defはスコープ(TeXではグループと呼ばれる)に影響されるので,同じスコープ内でのみ有効です.これを問答無用でグローバルにするための修飾子が\globalです.TeXのマクロは「動的スコープ」を持つといえます.Perlでいうところのlocalがついているようなものです.

また,TeXのマクロの引数には改段落はデフォルトでは許されません.この仕様は一種のリミッターになっているのですが,このリミッターを解除するのが\longという修飾子です.さらに,マクロの引数中で使うことができないマクロを定義するために\outerという修飾子が定義されています.

結果,\global/\long/\outerの修飾子と\defを組み合わせてマクロを定義することになります.これら三つの修飾子は排他的ではありません.

\globalについては以下のような動きになります.

\def\macroA#1{#1はカバ.}
\macro{アヤメちゃん}%%%アヤメちゃんはカバ.

{%
\def\macroA#1{はサル.}
\macro{アヤメちゃん}%%アヤメちゃんはサル.
}%

\macro{アヤメちゃん}%%%アヤメちゃんはカバ.

{%
\global\def\macroA#1{はサル.}
\macro{アヤメちゃん}%%アヤメちゃんははサル.
}%

\macro{アヤメちゃん}%%アヤメちゃんははサル.

\longについはこのような感じです.

\def\longmacroA#1{#1」には複数の段落がある.}
\longmacroA{本日は晴天なり.
\par
明日は雨かも.}%%%これはエラーになる.

\long\def\longmacroA#1{#1」には複数の段落がある.}
\longmacroA{本日は晴天なり.
\par
明日は雨かも.}%%%これならOK.

\outerはこんな感じです.

\def\macroA#1{#1」は本当です.}
\outer\def\outermacro#1{#1はカエルではありません.}

\macroA{\outermacro{アヤメちゃん}}%%%エラーになります.

! Forbidden control sequence found while scanning use of \macroA.

\def\macroA#1{\outermacro{#1}}
\outer\def\outermacro#1{#1はカエルではありません.}

\macroA{アヤメちゃん}%%これはOK

もっとも,LaTeX2eでは\outerはほとんど使われておらず,フロート関係で使われているのみです.フロート系環境はマクロの引数にはできないのです.

\defと\edef

TeXのマクロの基本は\defなのですが,TeXのマクロは「単なる文字列の置き換えに過ぎない」という根本的な大原則があります.この原則を踏まえないでTeXのマクロを作ろうとすると絶対にいつかしっぺ返しをくらいます.例えば

\def\temp{太郎}
\def\marcoA#1{\temp#1の子です.}

\macroA{}%%%太郎は女の子です.

\def\temp{花子}
\macroA{}%%%花子は男の子です.

のように動作します.\macroAの中の\tempはマクロが定義されたときの値が使われるのではなく,マクロが使用されたときの値が使われるのです.あくまでも「置き換え」なので,\macroA{XX}は「\tempはXXの子です.」に置き換わるだけです.そして置き換わった時点での\tempが使われます.

しかし,これはとても不便なことがあります.そのマクロが定義されたときの値をそのまま保持して使いたいこともよくあります.そのようなときに使うのが\edefです.\edefを使うと,

\def\temp{太郎}
\edef\marcoA#1{\temp#1の子です.}

\macroA{}%%%太郎は女の子です.

\def\temp{花子}
\macroA{}%%%太郎は男の子です.

となります.つまり,\edefは定義された時点で「\temp は#1の子です.」の\tempをそのときの\tempの値を使って「太郎は#1の子です.」と展開して,それを\macroAと定めます.

したがって,TeXのマクロは\def/\edefに\global/\long/\outerの修飾子を組み合わせて定義することになります.そして,展開をいかに自在に制御するかがTeXのマクロ作成においては極めて重要なテーマです.

本が出ませんね

Haskell本,それも日本人による日本語の本の三冊目以降が出ませんね.Haskellの「尖がった」ところが前面にでるような本が出てくれると勉強になるのですが.とりあえず現在頑張ってParsecのドキュメント読み中.

  • ParsecでRPNからASTを作る

なんてくらいのこと(簡単な文法だけでも)が出来ればきっと基本は理解できたと思っていいんだろうな.