shaitan's blog

長文書きたいときに使う.

TeXを使ってすみちゃまともっと仲良しになる方法 (\lBで\mathbb{B}を出したい)

\lB で \mathbb{B}を出すマクロ (after しゃいたん) - TeX 備忘録

\lA, \lB,..., \lZ を\mathbb{A}, \mathbb{B},..., \mathbb{Z}として定義したいとのことです.
もちろん,

\newcommand{\lA}{\mathbb{A}}
\newcommand{\lB}{\mathbb{B}}
...
\newcommand{\lZ}{\mathbb{Z}}

と書けば十分ですが,もっとカッコ良くしたいとのことなので,次のようにしてみました.

\makeatletter
\@tempcnta\z@
\loop\ifnum\@tempcnta<26
\advance\@tempcnta\@ne
\expandafter\edef\csname l\@Alph\@tempcnta\endcsname{\noexpand\mathbb{\@Alph\@tempcnta}}
\repeat
\makeatother

方針

\def\lA{\mathbb{A}}...\def\lZ{\mathbb{Z}} (っぽい感じ)に展開されるマクロを書けば良い.

A,..., Zは\@Alph1,..., \@Alph26 で出せる(cf. latex.ltx ll.1864-7*1 ).
数字の部分はlatex.ltxで定義されてる\@tempcntaというカウンタを使うことにしよう(cf. latex.ltx l.833).
当然ループマクロを使いたい.\loop...\reapeat を使うことにする(cf. latex.ltx ll.101-3).
0で初期化(\@tempcnta\@z)しておいて,ループの繰り返しは25まで(\ifnum\@tempcnta<26).
最初にインクリメント(\advance\@tempcnta\@ne)してやれば,結局\@tempcntaが1から26の場合についてループの中身が実行される(\@tempcntaが1から26の場合のループの中身が順番に展開されたものにループマクロが展開される,というとより正確か?).


定義する時点で\@Alph\@tempcntaは展開されていないといけない.

\mathbb{A}
\edefを使えば展開されたものが定義される.ただし,\mathbbは\lAが使用される時点で数式モードであるかどうかの判定をしたいので展開したくない.\noexpandを前置しておく.
\lA
\csname...\endcsnameの中身はその時点で展開されるので\csname l\@Alph\@tempcnta\endcsnameでOK.また,\csname...\endcsnameを展開したやつを\edefに食わせたいから,\edefの前に\expandafter.

文字@を含む命令*2を使うので,これをプリアンブルに直接書くなら\makeatletterと\makeatotherで挟む(cf. TeX by Topic 2.3).
この内容をstyに書き出して\usepackageするなら勝手に\makeatletterしてくれるので必要ない(cf. latex.ltx ll.7451-4, 7460-61, 7520-53).
これはsty等の中身で触られたくない命令に@を入れておけば普通は本文中でうっかり上書きされなくてハッピー!というのを目的とした仕様のはずだけど,そんなうっかりがありうるような平凡な名前をつけてるとどのみち他のstyとかと衝突するんじゃないんだろうか?

*1:バージョンによって相違があるかもしれない.以下いちいち断らない.

*2:正確にはコントロールワード.通常,本文中で使用可能な@を含むコントロールシーケンスはコントロールシンボルである\@だけであり,これは大文字+ピリオドが文末に来るときにA\@.のように使うとスペースがいい感じになる(cf. latex.ltx l.1307).