ホーム‎ > ‎

LaTeXマクロ入門

マクロとは

  • トークン列を別のトークン列に置き換える
  • 例えば、 \TeX というマクロは T\kern -.1667em\lower .5ex\hbox {E}\kern -.125emX\@ として定義されている。

コマンドとマクロの関係

  • コマンド:TeX 処理系や文書への命令。
  • マクロ:別のトークン列に置き換わるコマンド。
  • LaTeX や各種パッケージが提供するコマンドは全てマクロとして実装されている
    • \newcommand も実際はマクロ
  • マクロでないコマンドはTeX処理系が直接処理するコマンドで、TeX primitive と呼ばれる。
    • 例:\def, \par, \displaystyle, \jobname, \left, \right
    • 使う側としては、特定のコマンドがマクロとして実装されているか TeX primitive なのかは意識する必要はない。


コマンド名について

  • バックスラッシュ \ の後にアルファベットを並べる。数字や記号は使えない。
    • 例:\section
    • このパターンの場合、直後の空白文字は無視される。
  • バックスラッシュの後に記号1文字
    • 例:\!\,
  • 半角チルダ ~ (TeXの特殊文字)
    • 「カテゴリーコードの変更」を使えば、半角チルダ以外にも、任意の文字をコマンド名扱いにできる。

マクロの使い方

  • コマンド名の後に引数を書く
  • 必須の引数は波カッコ { } で囲む
    • { } は入れ子にできる
  • 必須の引数が1文字またはコマンド名1個の場合は { } を省略できる
    • \frac12\frac{1}{2} と等価。
    • \newcommand\Real{\mathbf{R}}\newcommand{\Real}{\mathbf{R}} と等価
    • 「1文字の場合は { } を省略できる」と書いたが、一部のコマンドはアスタリスクの有無で動作を変えるので、そういう場合は { } を省略すると挙動が変わってしまう。開き角カッコ [ についても同様
    • 「省略できる」からといって省略するかどうかは、書く人の美意識次第だが…。
  • 省略可能な引数を与える時は角カッコ [ ] で囲む。
    • 角カッコ [ ] は入れ子にできないが、波カッコ { } の内側にある角カッコ [ ] は考慮されない。
  • 一部のコマンドは、コマンド名の直後にアスタリスク * を置くことによって挙動が変わる
    • 例:\section*, \newcommand*

自分でマクロを定義する:\newcommand

  • \newcommand{コマンド名}{内容}
  • 例:\newcommand{\Real}{\mathbf{R}}
    • \Real コマンドは展開時に \mathbf{R} に置き換えられる

引数を取るマクロを作る

  • \newcommand{コマンド名}[引数の個数]{内容}
  • コマンド名と本体の間に、オプション引数として引数の個数を渡す。
  • 「内容」のところに書いた #1#9 が引数に置き換えられる(引数の個数は最大で9個)
  • 例:\newcommand{\transpose}[1]{{}^t\,#1}
    • \transpose{A}{}^t\,A に置き換えられる。

引数を省略可能にする

  • \newcommand{コマンド名}[引数の個数][デフォルト値]{内容}
  • 最初の引数を省略可能にできる。引数の個数の後に、省略時のデフォルト値を指定する。
  • 2番目以降の引数は省略可能にできない。
例:
\newcommand{\norm}[2][2]{\left\lVert #2\right\rVert_{#1}}
\norm{x} % デフォルトでは 2-ノルム
\norm[\infty]{x} % ノルムの種類をオプション引数で指定できる


長い引数と短い引数

  • 長い引数:引数の中に空行を含められる
  • 短い引数:引数の中に空行を含められない
    • 目的:波カッコ } の閉じ忘れのミスを発見しやすくする
    • TeX 的には空行は \par コマンドと等価なので、短い引数の中に \par は書けない
  • \newcommand の直後にアスタリスク * を置くと、定義するマクロの引数が短い引数になる
  • \newcommand*{コマンド名}[引数の個数][デフォルト値]{内容}
例(\section の閉じかっこ忘れ):
\section{この定理がすごい!2016

2016年の大賞はこれだ!!!

というソースをコンパイルすると Paragraph ended before 〜 was complete というエラーが出る。

\newcommand の制限:

  • 省略可能引数の位置は最初で固定で、1つしか持てない
  • アスタリスク * の有無で挙動を変えるコマンドは定義できない
  • 長い引数と短い引数を混在できない
ちなみに、 LaTeX が提供する \newcommand 自体は
  • 省略可能な引数を途中に2つ持っている(引数の個数と、デフォルト値)
  • アスタリスクの有無で挙動を変える
  • 長い引数と短い引数が混在している(「コマンド名」の方は短い引数で、「内容」は長い引数)

という仕様なので、 \newcommand を使って \newcommand と同じ仕様のマクロを定義することはできない。


マクロのスコープについて

  • 定義したマクロはどの範囲(スコープ)で有効か?
  • スコープが区切られる条件:
    • 単体の波カッコ { } (「単体の」と書いたのは、「マクロ引数としての { } ではない」という意味)
    • 環境の中
  • \renewcommand で上書きしても、スコープの外に出ると上書きした定義は忘れられる。

例:

\begin{enumerate}
% \labelenumi マクロを上書きする
\renewcommand{\labelenumi}{(\theenumi)}
\item hoge
\item piyo
\end{enumerate}

\begin{enumerate}
% \labelenumi マクロの定義はデフォルトのものに戻っている
\item A
\item B
\end{enumerate}


環境


  • 環境は LaTeX 特有の概念である(TeX レベルでは環境という概念はない)
  • 環境の名前はコマンド名と違い、 アルファベット、数字、アスタリスクを含めることができる
  • 環境は \newenvironment で定義できる
    • \newenvironment{名前}[引数の個数][デフォルト値]{最初}{最後}
    • 「最初」の中にある #1#9 が引数で置き換えられる
    • 「最後」の部分では引数は参照できない
  • マクロと同様に、環境は引数を受け取れる(使う際は \begin{} の直後に引数を与える)

マクロと環境の関係

  • \begin{hoge}\end{hoge}
    は大雑把にいうと
    \begingroup\hoge\endhoge\endgroup
    と等価
  • 重要:環境と同じ名前のマクロを共存させることはできない

\def vs \newcommand

LaTeX においてマクロを定義する方法として \def\newcommand の2種類が使われているが、どう違うのか?

要約

君たちの99%はどうせ TeX のマクロの詳細なんて理解していないんだから、安全のために \def ではなくて \newcommand を使いましょう

使い方の違い

  • \def〈コマンド名〉引数の指定{内容}
  • \newcommand{コマンド名}[引数の個数][デフォルト値]{内容}
  • \def はマクロではないので、コマンド名を { } でくくることはできないし、内容を囲む { } を省略できない
    • \newcommand\A\B\def\A\B は意味がまるっきり違う
  • \def ではオプション引数をとるマクロは簡単に定義できない(TeX プログラミングが必要)

挙動の違い

  • 既存の同名のマクロ(または環境)があっても、 \def は問答無用で上書きする
    • →意図せずに既存のマクロや環境を壊す可能性がある。危険!
    • (常識的な範囲ではそのような「事故」はそうそう起こらないと思うが…。)
  • \newcommand は既存のマクロ等があるとエラーになる
    • →意図せずに既存のマクロや環境を壊すことがない。安全!
    • 上書きするには \renewcommand を使う
  • \newcommand では定義できない名前がある(end から始まる名前および、\relax
    • 安全のためにこうなっているのであり、できることが少ないから \newcommand は貧弱だという意味ではない

リンク集


Comments