algebraic dialy(2015年12月)

なにかあったらすぐtwitterに書いてしまうのであまり更新しません

[an error occurred while processing this directive]

射の合成をするための命令を定義してみる

この記事はTeX & LaTeX Advent Calendar 2015 4日目です。 3日目は@p_typoさんの今さら人に聞けないローマ数字とその組み方でした。 5日目は@neruko3114さんのLaTeXで得られる出力をMSWordのそれに近付けようとするためにです。

皆さんも普段からTeX/LaTeXで色々命令を定義して使っていると思います。私も色々定義していますが、今回は初心者大歓迎(重要)の「今さら人に聞けない、TeXのキホン」がテーマとのことですので、私が普段使っている命令を紹介することで、「TeXのキホン」が理解できたらいいなぁと思います。

私がLaTeXを使うのは数学に関する文書を作るためですが、最近は特に圏論について色々書いているので、射(写像)の合成を頻繁にします。2つの射(写像) f: x→y と g: y→z の合成は g\circ f と書くと思いますが、「fを適用して、gを適用する」のに g ⇒ f の順でタイピングするのは非常に難しいです(まあ手書きするときも同じ問題があるのですが)。

そこで、引数を f ⇒ g の順で与えたら g\circ f を出力するような命令(ここでは \compo とすることにする)を作ってみたいと思いました。

簡単にやるには \newcommand{\compo}[2]{#2\circ #1} とでも書けば、 \compo{f}{g}g\circ f が出ます。が、これだと3つ合成する場合 \compo{\compo{f}{g}}{h} となり、書きやすいとは言えません。 ここは \compo{f}{g}{h}h\circ g\circ f と出て欲しいです。

このように引数の数を可変にしたい場合どうすればいいかというと、次のような方法で実現できることが分かります。 まず \compo\newcommand{\compo}[2]{\compo{#2\circ #1}} のような定義にします。すると、\compo{f}{g} と書いた場合 \compo{g\circ f} と展開されるわけです。つまり \compo{f}{g}{h} と書いた場合は \compo{g\circ f}{h} 即ち \compo{h\circ g\circ f} と展開されます。ただ、これでは処理がいつまで経っても終わらない、というか命令 \compo から見るとどこまでが引数なのか分からないので、終わりを明示してやる必要があります。

そこで、とりあえず「第二引数に \relax が指定された場合はそこで処理を終了する」ということにします(\relax が大変便利な命令であることは2日目の\relax の使い方 12連発で見ましたね!!)。つまり、\compo

と出力するように変えてやるわけです。こうすれば \compo{f}{g}{\relax}g\circ f となるし、\compo{f}{g}{h}{\relax}h\circ g\circ f となります。TeXにはいわゆるif文的な命令があるので、それを使えばこれはできそうです。なのでそれをやってみると、以下のようにすれば良さそうです……

\newcommand{\compo}[2]{
    \ifx#2\relax
        #1
    \else
        \compo{#2\circ #1}
    \fi
}

(※ \ifx#2\relax の部分が「#2\relax に等しいならば」を表します。)

が、これはやってみると上手くいきません。展開順がどうとか色々あってそんなに簡単ではないようです。で、色々調べて試行錯誤してみたところ、次のように書くと上記が実現できることが分かります。

\newcommand{\compo}[2]{
    \def\compox{\compo{#2\circ #1}}
    \ifx#2\relax 
        #1 
    \else 
        \expandafter\compox
    \fi 
}

みんなの大好きな \expandafter ですね!!!! (\expandafter についてはここでは触れませんが、「TeXのキホン」なので \expandafter のプロが何日目かに解説してくれるでしょう)

これでもいいですが(いや、よくないところはあるんですが)、これだと一々 \relax を後ろに付ける必要があり、面倒だし忘れそうです。そこで一番後ろに \relax を付加する命令も用意しましょう。どういうことかというと、新しい命令 \componew\newcommand{\componew}[1]{\compo#1{\relax}} と定義します。こうすると例えば \componew{{f}{g}} とすれば \compo{f}{g}{\relax} となるので g\circ f が出力されるし、 \componew{{f}{g}{h}} とすれば h\circ g\circ f が出力されます。(ただ、中括弧が二重になってしまうので、どっちもどっちとも言えますが…。) ただ、1日目の完全攻略! LaTeX 命令の"引数の規則"の通り、 \componew{{f}{g}{h}} は実は \componew{fgh} と書けるので、\componew の方が便利だと思っています。

と、こんな感じで随分前に命令を作ってずっと使っています(特に圏論のPDFでは使いまくっています)が、便利だし特に問題も起きてないので、折角のこのタイミングで書いてみました(あと、公開すればTeXのプロがまずい点を指摘してくれると思って…)。上で作った命令は説明用のものなので、実際使っているのは以下の通りです。(下記はスタイルファイル用になっているのでスタイルファイルに書いてください)

\def\compo#1{
    \algd@compo#1\algd@end
}

\def\algd@compo#1#2{
    \def\algd@temp{\algd@compo{#2 \circ #1}}
    \ifx#2\algd@end
        #1
    \else
        \expandafter\algd@temp
    \fi
}

\def\algd@end{\algd@end@}