TeXマクロにおける\@namedef と \def\csname の違い
はじめに
TeXやLaTeXでマクロを定義するとき、静的な名前や動的な名前に応じて使い分けられる方法として、\@namedef
と \def\csname ... \endcsname
があります。
どちらもマクロ(コマンド)の名前を定義する手段ですが、使い方や目的に微妙な差があるので、本記事では、それぞれの特徴や活用方法について備忘録も兼ねて整理します。
@namedef の概要
\@namedef
は、名前が明確に分かっている マクロを簡潔に定義するための、高レベルなマクロコマンドです。次のように書くと、与えた名前のマクロが定義されます。
\@namedef{<名前>}{<マクロの内容>}
-
<名前>
は文字列として与え、これがマクロ名です。 -
<マクロの内容>
が、そのマクロを展開した際の出力です。
例
\@namedef{foo}{Hello, World!}
\foo % => Hello, World!
上記の例では、foo
というマクロが定義され、\foo
と書くと「Hello, World!」が出力されます。名前の指定に {foo}
のように {}
が必要である点がポイントです。
\def\csname ... \endcsname の概要
\def\csname ... \endcsname
は、動的に名前を組み立てて マクロを定義するためのコマンドです。\csname
と \endcsname
で囲まれた部分がマクロ名として認識され、\def
によって定義されます。
\def\csname <名前>\endcsname{<マクロの内容>}
-
<名前>
は動的な文字列の組み合わせも含めて指定できます。 -
<マクロの内容>
は、マクロを展開した際の出力や挙動です。
例
\def\csname foo\endcsname{Hello, World!}
\foo % => Hello, World!
上記の例では、\csname ... \endcsname
によって foo
という名前のマクロが定義され、呼び出すと「Hello, World!」が出力されます。
使い分けと違い
静的な名前しか必要としない場合は \@namedef
が便利ですが、名前を部分的に変数や他のマクロから動的に生成したいときは \def\csname ... \endcsname
が力を発揮します。以下の表に、それぞれの特徴をまとめます。
項目 | @namedef | \def\csname ... \endcsname |
---|---|---|
定義レベル | 高レベルマクロ | 低レベルマクロ |
名前の指定方法 |
{<名前>} で静的に指定 |
\csname <名前>\endcsname で動的に構成 |
名前の展開の仕方 | 完全に展開された文字列をそのまま渡す必要がある | 内部で段階的に展開可能 |
動的な名前の定義 | 可能。ただし事前に完全展開する必要がある | 可能。部分的に展開された状態でも最終的に組み立ててくれます |
主な用途 | 静的な名前を手早く定義するとき | 名前を変数などから動的に組み立てる必要があるとき |
@namedef を使った動的な名前の生成
\@namedef
は、静的な名前の定義に向いている一方、多少の工夫をすれば動的な名前を定義することもできます。その際、定義したいマクロ名に含まれる変数は 事前に完全展開 しておかねばなりません。
例:変数を使ってマクロ名を作る
\edef\arrayname{myarray} % "myarray" という文字列を \arrayname に格納
\@namedef{\arrayname}{This is a dynamically named macro.}
\myarray % => This is a dynamically named macro.
-
\edef\arrayname{myarray}
で、文字列 "myarray" を\arrayname
に格納します(ここで展開されます)。 -
\@namedef{\arrayname}{...}
によって、\myarray
というマクロが定義されます。
このように、\edef
などで文字列を先に確定させ、完全な形で \@namedef
に渡す必要があります。
\def\csname ... \endcsname を使った動的な名前の生成
\def\csname ... \endcsname
は、\csname
内部で必要に応じて文字列を展開しつつ最終的なマクロ名を組み立てます。完全に展開された状態を渡さなくても、途中で展開が行われるため柔軟に名前を生成できます。
例:部分的な変数展開
\def\prefix{data}
\def\csname \prefix@1\endcsname{Element 1}
\data@1 % => Element 1
-
\csname \prefix@1\endcsname
では、\prefix
が順次展開されて"data@1"
という文字列を最終的なマクロ名とします。 - 結果として、
\data@1
というマクロが定義されます。
注意点・まとめ
-
\@namedef
は名前を完全に展開した上で渡す必要があるため、変数を使う際には\edef
などを駆使して事前に文字列を確定させる必要があります。 -
\def\csname ... \endcsname
は低レベルコマンドであり、内部で必要に応じて段階的に文字列を展開してくれます。動的な名前を作る際に便利ですが、慣れないうちは読み書きしにくいです。 - 静的な名前が分かっている場合は
\@namedef
を使い、名前を変数から動的に組み立てる場合は\def\csname ... \endcsname
を使うと良いと思います。
読んでいただきありがとうございました。
Discussion