L^{A}TEX 2εマクロ備忘録�

ver-1.2

平成 14 年 10 月 21 日

目次

1 step0 （緒言） 2 1.1 おことわり . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 1.2 はじめに . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2

2 step1 （計算） 3

2.1 引数のパターンマッチング . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 2.1.1 /def と /newcommand . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 2.1.2 引数のパターンマッチング . . . . . . . . . . . . . . . . . . . . . . . . . . . 3

2.2 文字のカテゴリコード . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 2.3 定義の有効範囲 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 2.4 展開 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5

2.4.1 マクロの展開 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 2.4.2 展開のタイミング . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 2.4.3 展開の順 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7

2.5 計算のまとめ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 2.5.1 数値の場合 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 2.5.2 長さの場合 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 2.5.3 数値・長さの変換 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 2.5.4 続・長さの場合 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 2.5.5 /the のこと . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 2.5.6 カウンタ補筆 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 2.5.7 例 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11

3 step2 （補筆） 13

3.1 汎用性 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 3.1.1 記号の大きさの汎用性 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 3.1.2 図の大きさの汎用性 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15

3.2 条件分岐補筆 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 3.2.1 /if . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 3.2.2 /ifx . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 3.3 おまけ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19

3.3.1 ￥記号 10 様 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19

4 おわりに 20 4.1 あとがき . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20

1 step0 （緒言）

1.1 おことわり

この備忘録は前編に引き続いて著者がマクロを学習した際のメモをまとめたものであり、あくまでも個人的な経験を元に作られています。もともと他人の目に触れる目的で書かれていませんので記述に関してかなり不親切な部分があります。なおかつ、学習途上の不正確な理解が反映されているところも多いかと思いますので、使用についてはある程度の疑心をもってかかってください。

1.2 はじめに

前編で初級マクロの作製について一通りの解説を試みました。もちろん、どのあたりが初級だとかいうことも曖昧ですから、不十分な点が多々あったかと思われます。そこで今回は前編より一歩踏み込んだ内容の記述を行います。しかしながら、一足飛びに中級に移行するわけにもいかないので、目標を中級の一歩手前というところにして進めていきたいと思います^{1}。

さらに具体的にすると、前編で触れなかった部分でありながらよく使うところの新記、前編で中途半端に触れたところの補完をします。とりわけ今回は次のマクロ群の理解を当面の目標にします。これは「磯崎」本 p177 にあるものと同様のもので、少数計算を定義するマクロのうちの乗算部分です。

\newdimen\rval
{\catcode`\p=12\catcode`\t=12\gdef\Rval#1pt{#1}}
%
\def\Rmulti#1#2#3{\rval=#1pt\rval=#2\rval
\edef#3{\expandafter\Rval\the\rval}}

ここには２つのマクロが定義されています。

• ディメンションを実数化するマクロ

• 小数計算での乗算をするマクロ

そしてそれぞれに初級で触れられなかった以下の重要なマクロテクニックが含まれています。

• 文字のカテゴリコード

• 引数のパターンマッチング

• 展開制御

1どこからが中級やねん？

• ディメンションを用いた小数値の乗算^{2} そこで、以下では当面これらについて触れていきます。

前編に引き続いて以下の文献を参照します。

• 改訂新版 TEX ブック Donald E.Knuth 著斎藤信男 監修 鷺谷好輝 訳

• L^{A}TEX 2εfor WINDOWS Another Manual Vol.2 乙部厳己 江口庄英 著

• L^{A}TEX 自由自在 磯崎秀樹 著最後のものは特に文中単に「磯崎」本と省略します。

2 step1 （計算）

2.1 引数のパターンマッチング

2.1.1 /def と /newcommand

前編で両者には本質的な違いがないとしました。しかし元々の働きは異なります。詳細は「磯崎」本に譲りますが

• \def は定義したいコマンド名（コントロールシーケンス）が既に定義されているかチェックしない

• \newcommand は定義したいコマンド名（コントロールシーケンス）が既に定義されているかチェックする

• \def は引数のパターンマッチングの機能を持つという大きな違いがあります。前編で \def を多用したのは再定義でもエラーを気にせずに使える点などが個人的に気に入ったからです。しかしうっかりして大切なコマンドを書き換えてしまう恐れもあるので通常は \newcommand の使用を推奨されることが多いようです。さて、それから \newcommand では再定義がエラーになりますがこの場合には \renewcommand がありますのでそちらを使います。このあたりの扱いは L^{A}TEX 流では統一的なものです。

2.1.2 引数のパターンマッチング

引数のパターンマッチングとは簡単に言えば、引数の形を特定の文字列の形で制御して与えることが出来る機能です。ただ、これだけでは何のことかよくわからないので例を示します。

\def\A#1{#1-1}

という単純なマクロを用意します。このときこのマクロの引数は { } を用いて通常 \A{35} と与えるものだと思います。この結果は 35-1 となります。次に

\def\A#1-1{#1-1}

2そのままやんけ！

のように変えてみます。引数のところが不思議な感じですが気にせずに \A35-1 としてみます。こうすると 35-1 が得られます。これだけではわかりにくいのでもうひとつ今度は

\def\A#1#2{#1+#2}

とします。このマクロに対して \A{12}{34} とすれば当然 12+34 を得ます。これに対して

\def\A#1+#2#3{#1+#2#3}

とマクロを変えると \A12+34 に対して 12+34 を得ます。つまりここでは + の前までが #1 となりそれ以降は一文字ずつの対応となります。このようにパターンマッチングとは引数の中にある特定の文字列を入れておいて、入力文字との対応で引数をコントロールする機能ということになります。この機能は文字列の取り出しにとても有効です。例えば bcde の中の前の２文字だけを取り出したいのであれば

\def\A#1de{#1}

というマクロを定義します。ここで \A bcde とすれば bc を得ます。この機能を使うとディメンションから単位をはずすことが可能になります。 10pt という値から pt を取り除けば 10 という数値となります。実際、このようにしてディメンションを数値化（実数化）することが可能となります。そこで

\def\A#1pt{#1}

というマクロを定義して \A10.0pt とすれば確かに 10.0 という出力は得られるのですが

\dimen1=10pt
\def\A#1pt{#1}

の場合には \A\the\dimen1 という入力に対してエラーが起こります。これを正しく出力させたい場合には定義を

\dimen1=10pt
{\catcode`\p=12\catcode`\t=12\gdef\A#1pt{#1}}

のように変えた上で \expandafter\A\the\dimen1 と入力しなければなりません。このようにすると確かに 10.0 が得られます。

なぜそのようにしなければならないのかを考えるのが次の課題です。

2.2 文字のカテゴリコード

前回のところでなぜ直接与えた 10.0pt の pt がはずせてディメンションの pt がはずせなかったのでしょうか？簡単に言えば、それは前者がアルファベット文字 p と t で与えられた pt であるのに対して、後者は単位としての pt であったためです。見かけは同じこの pt がなぜこのように異なる役割を果たすかという疑問に答えるのが文字のカテゴリコードです。ディメンションで使われる単位としての pt はそれぞれ p と t に対してアルファベットではないという趣旨の属性が与えられています。この属性を表すカテゴリコードは 12 です。これに対して通常のアルファベットのカテゴリコードは 11 です。ですから引数のパターンマッチングで pt をとろうとするならば、マクロ定義中の pt をカテゴリコード 12 に変更してやらなくてはいけません。そこで用いるのが

\catcode です。

基本の書式は \catcode`\文字=変更後のカテゴリコードです

例

\catcode`\p=12
\catcode`\t=12

これで p ,t は通常のアルファベットとしてでなく、単位などで使用される特殊文字として認識されます。

さらに、これを使った例としては \makeatletter があります。通常使えない @ はカテゴリコードが異なるからで、これを使えるようにするのが \makeatletter というわけです。実際このコマンドは

\def\makeatletter{\catcode`\@=11}

で定義されています。同様に \makeatother も定義されていますがこちらの中身は考えてみてください^{3}。

2.3 定義の有効範囲

マクロ定義で

\def\A{123}

に対して \A は当然 123 と出力されます。しかし

{\def\A{123}}

とすると、 \A に対してはエラーが起こります。これはマクロ定義が { } によって挟まれいるためで、その中だけでのみ定義されたものとして見なされてしまうからです。このような { } のくくりをグループといい、グループ化することをグルーピングといいます。マクロをグループの外でも有効にしたいのであれば、 \gdef を用います。このことと文字のカテゴリコードのところを踏まえれば

{\catcode`\p=12\catcode`\t=12\gdef\A#1pt{#1}}

の意味がわかると思います。

2.4 展開

2.4.1 マクロの展開

これまで何気なくマクロを定義し使ってきましたが、マクロの定義は通常のプログラミング言語などとは若干その扱いが異なります。そのあたりを見ていくことにします。

まずは以下のマクロ群を実行したときにそれぞれ \A, \B の値は何になるでしょうか？

3解答は乙部 p258

\def\A{1}
\def\B{\A}
\def\A{2}
\A
\B

普通のプログラムに慣れている人ならば、 \A, \B それぞれの値は 2, 1 をそれぞれ得るものと思いがちです。それは、はじめに \A は 1 となり、続いて \B も 1 となり、続いて再び \A は 2 に置き換えられると考えるのが普通だからです。ところが実際にはこの出力はそれぞれ 2, 2 となります。確かに \A は 2 となるのですが、 \B は 1 とはなりません。その理由はマクロの定義と実際の実行（展開）がずれているためです。わかりやすく言うと、マクロは定義されただけでは実行されないのです。マクロは \A や \B が現れたときにはじめてその定義に基づく処理（展開）をします。したがって、この例では \B が与えられたときにはじめて上記の３つのマクロが展開されることになります。そのときには \A は２回目の再定義により 2 となり、その値が \B となるわけです。また今度は次のような場合を考えます。

\def\A{1}
\def\B{\A}
\A
\B
\def\A{2}
\B

この例では、はじめの \A は 1 となり、また次の \B も 1 となります。それは、 \A が再定義される前に \A, \B が置かれているのでその時点で展開されるからです。さらに進んで次の \B のところは \A の再定義の後なので 2 という出力になります。

このように、マクロの定義、特に複数のマクロを定義するときには、展開ということを頭に置いておくことが大切です。特に他のプログラムに慣れている人ほどこのことを忘れがちになります。

展開の詳細を知るにはトークンや「口」、「胃袋」などの概念が必要です。初中級の範囲とレベルを超えると思いますから、そのことについては TEX ブック等を参照してください。

2.4.2 展開のタイミング

それではつぎのようなマクロを考えてみます。

\def\A{1}
\def\A{\A+2}
\A

出力として 2+1 を期待しているのですが、結果は思うようにはなりません。これを実行すると TEX は途中で何も言わなくなって止まってしまいます。これは無限ループに入ってしまったからです。先の展開のことでお分かりのようにはじめの \def\A{1} が展開されることが前提の \def\A{\A+2} ですがそのようにうまくはいきません。ではどうしたらいいでしょうか？それには、強制的に定義時点で展開させれば良いということになります。この定義時点での展開をするのが \edef です。これを使用して

\def\A{1}
\edef\A{\A+2}
\A

とすれば 1+2 が得られます。同様のことをグループ外でも有効にしたいときは \xdef を使用します。

2.4.3 展開の順

\expandafter について触れます。正確さに欠けますが、次のように使用するものと考えてください。

基本の書式は \expandafter{あとに展開したいマクロ}{先に展開したいマクロ} です

例

\dimen1=10pt
{\catcode`\p=12\catcode`\t=12\gdef\A#1pt{#1}}
\expandafter\A\the\dimen1

この結果が 10.0 となることは先に見た通りです。

さて、ここまでくると当初の当面の目標であったマクロ群の理解ができることになります。以下に再掲しますからその意味を改めて理解してみてください。

\newdimen\rval
{\catcode`\p=12\catcode`\t=12\gdef\Rval#1pt{#1}}
%
\def\Rmulti#1#2#3{\rval=#1pt\rval=#2\rval
\edef#3{\expandafter\Rval\the\rval}}

2.5 計算のまとめ

これまでの事柄を整理し、計算についてまとめてみることにします。

2.5.1 数値の場合

まず数値の場合です。整数計算しかできません。

例

\count1=10
\count2=20
\count3=30
\count4=40
\count5=50

としておきます。四則演算

\advance \count1 by \count2
\advance \count2 by -\count3
\multiply \count3 by \count4
\divide \count5 by \count4

の結果はそれぞれ 30 -10 1200 1 となります。さらに代入

\count6=\count4
\count7=-\count4

の結果はそれぞれ 40 -40 となります。

2.5.2 長さの場合

同様にディメンション（長さ）の場合には

例

\dimen1=10pt
\dimen2=20pt
\dimen3=30pt
\dimen4=33.3pt

としておきます。四則演算のうち加減

\advance \dimen1 by \dimen2
\advance \dimen2 by -\dimen3
\advance \dimen3 by \dimen4

の結果はそれぞれ 30.0pt -10.0pt 63.3pt となります。また長さの場合には実数倍が容易に出来て

\dimen5=-\dimen4
\dimen6=3\dimen4
\dimen7=0.5\dimen4

の結果はそれぞれ -33.3pt 99.90001pt 16.65pt となります。ここで \dimen6 の結果が正確ではなく、近似値になっていることに注意します。

2.5.3 数値・長さの変換

数値と長さを変換します。まず、数値を長さに変換します。そのためには単に pt または \p@ をつけます。

例

\count1=10
\count2=20

に対して

\dimen1=\count1pt
\dimen2=\count2pt

の結果はそれぞれ 10.0pt 20.0pt となります。このとき pt はもはやアルファベットではないことに注意します。次にその逆を考えます。長さを数値に換えるには、当初ここで目標にしていた例のマクロ群を用

います。

例

\dimen1=10pt
\dimen2=20pt
\dimen3=30pt

とマクロ

{\catcode`\p=12\catcode`\t=12\gdef\Rval#1pt{#1}}

に対して

\expandafter\Rval\the\dimen1
\expandafter\Rval\the\dimen2
\expandafter\Rval\the\dimen3

の結果はそれぞれ 10.0 20.0 30.0 となります。 2.5.4 続・長さの場合

長さの場合の四則演算のうち乗法に関して

例

\dimen1=10pt
\dimen2=33.3pt
\dimen3=0.5pt

とマクロ

{\catcode`\p=12\catcode`\t=12\gdef\Rval#1pt{#1}}

に対して

\dimen1=\expandafter\Rval\the\dimen1\dimen2
\dimen2=\expandafter\Rval\the\dimen2\dimen3

の結果はそれぞれ 333.00003pt 16.65pt となります。以上で通常の図表をかくときなどに使用するための計算については、ほぼ間に合うものと思い

ます。

2.5.5 /the のこと

カウンタやディメンションの値を表示するためのコマンド \the について蛇足ながら触れておきます。

\count0=10
\def\A{10}

に対して \the\count0 は正しく表示されますが、 \the\A はエラーになります。 \A のみで結果が表示されます。しかしながら

\count1=\count0
\count2=\A

などという代入文は使えます。この違いには充分に気を付けてください。

ちなみに年や月や日を取得する \year,\month,\day を表示させるには \the が必要です。また同様の働きを持つものとして \number がありますがここで詳しくは触れません。

2.5.6 カウンタ補筆

これまではカウンタの宣言等はすべてカウンタレジスタを \newcount で直接宣言してきました。これはいわば plain TEX 流の記述なのですが、この備忘録の統一的観点からこの形式にこだわって使ってきました。その分カウンタとカウンタレジスタをごちゃごちゃにして説明してきました。初中級ではまあそれでもいいか、という感じなのですが、これから中級に向かうにあたってはそろそろこのあたりもきちんとしなければならないのかも知れません。

さて、 plain TEX 流に対して、 L^{A}TEX 流の宣言が \newcounter です。この宣言では以下のようにカウンタ名には \ は不要です。もしもカウンタ名 step を宣言したとすればカウンタレジスタは自動的に \c@step となります。さらに、カウンタ step の値をインクリメントするには \stepcounter を、数値を比較するときなどは、 \value を使います。それぞれ以下の例を参考にしてください。

例これまでの記述ではつぎのようなやり方

\newcount\step
\loop
\ifnum\step<5
K
\advance\step by 1
\repeat

これは次のようにもできる

\newcounter{step}
\loop
\ifnum \value{step}<5
K
\stepcounter{step}
\repeat

また変則的には次のようにしても動く

\makeatletter
\newcounter{step}
\loop
\ifnum \value{step}<5
K
\advance \c@step by 1
\repeat
\makeatother

これで、 \the と \value の使い方の違いもおわかりいただけたかも知れない。

2.5.7 例

最後に数値計算の簡単な例を示して終わります。奥村 晴彦著 L^{A}TEX 2ε美文書作成入門にあるマクロで、曜日を与えるものです。

例

\def\曜{{
\count0=\year
\count1=\month
\ifnum\count1<3
\advance\count0 by -1
\advance\count1 by 12
\fi
\multiply\count1 by 13
\advance\count1 by 8
\divide\count1 by 5
\advance\count1 by \count0
\divide\count0 by 4
\advance\count1 by \count0
\divide\count0 by 25
\advance\count1 by -\count0
\divide\count0 by 4
\advance\count1 by \count0
\advance\count1 by \day
\count0=\count1
\divide\count1 by 7
\multiply\count1 by 7
\advance\count0 by -\count1
\ifcase \count0 日\or 月\or 火\or 水\or 木\or 金\or 土\fi}}

このマクロに対して

\the\year 年 \the\month 月 \the\day 日\曜曜日
\the\year 年 \the\month 月 \the\day 日（\曜）

の結果はそれぞれ 2002 年 10 月 21 日月曜日 2002 年 10 月 21 日（月）となります。

次は簡単な実数計算の例です。 2 次式の値を計算するマクロです。これは自作なのでやや不細工なところがありますがご勘弁ください。

例

\makeatletter
\def\qfval#1#2#3#4{
\newdimen\YY
\newdimen\XX
\newdimen\X
\newdimen\CS
\XX=#1\p@

\XX=#1\XX
\XX=#2\XX
\X=#1\p@
\X=#3\X
\CS=#4\p@
\advance \YY by \XX
\advance \YY by \X
\advance \YY by \CS
\expandafter\Rval\the\YY}
{\catcode`\p=12\catcode`\t=12\gdef\Rval#1pt{#1}}
\makeatother

このマクロに対して

\qfval{1}{1}{2}{3}
\qfval{0.5}{1}{2}{3}
\qfval{0.25}{2}{1}{4}

の結果はそれぞれ 6.0 4.25 4.375 となります。

3 step2 （補筆）

3.1 汎用性

マクロに汎用性を持たせるということを考えていきます。作ったマクロ、またはこれから作ろうとするマクロを長く使う為には、マクロそれ自身にある程度の汎用性を持たせる必要があります。単純なマクロは単純さ故の手軽さがある一方、ある部分では使えないといった融通の利かない面が出てきます。例えば相似記号を JIS2266 の∽で代用する場合に、通常の使用では問題無いものの、少しでも大きさを変えようと思えばすぐにそれは不可能であることがわかります。

また、図表をマクロにした場合などでは、大きさの指定を固定したままでは、その文書の全体のレイアウトバランスにマッチしなくなることが少なくないことでしょう。そういうときには例えばオプションで大きさを指定できたり、用紙の横幅のパラメータを取得して大きさをそれに応じた形にしていくなどの工夫が要ることも確かです。

あるいは数式関係ではあまり使いませんが、横組みと縦組みで異なる処理を要する場合や、使用するフォントによって変えなければならないことさえあります。

マクロに汎用性を持たせることは、単純な作製目的から一歩進んだ大切な事柄です。初中級のレベルでもこのことはやはり大切です。 3.1.1 記号の大きさの汎用性

新しい記号を作る際には特に気を付けておきたいものがこれです。通常の文章中では標準的なサイズしか用いないので困ることは少ないのですが、小さくしたりということがいつ必要になるか知れません。

・既存の記号を組み合わせて新たな記号を作る場合

既存の記号の組合せで作る場合には特に凝った工夫はありません。既存の記号自体が大きさの変化に対応してくれるからです。

例

\makeatletter
\def\SUBEQQ{\mathrel{\mathpalette\gl@align\subset}}
\def\SUPEQQ{\mathrel{\mathpalette\gl@align\supset}}
\newcommand{\gl@align}[2]{\lower.6ex\vbox{\baselineskip\z@skip\lineskip\p@
    \ialign{$\m@th#1\hfill##\hfil$\crcr#2\crcr=\crcr}}}
\makeatother

これは以前にも紹介した、部分集合記号を ⊂, ⊃ と = を組み合わせて作った例です。この新たな記号\SUBEQQ および \SUPEQQ はそのまま大きさ指定に対応し

$\scriptstyle{\SUBEQQ}$
$\scriptscriptstyle{\SUPEQQ}$

の結果は

⊂ =

⊃ =

となります。

・既存の記号を組み合わせたりしないで新たな記号を作る場合この場合には大きさの指定に対応する工夫が必要です。そのことを実現させるのが \mathchoice

です。

基本の書き方は \mathchoice{ディスプレイスタイルの場合}{テキストスタイルの場合}{スクリプトスタイルの場合}{スクリプトスクリプトスタイルの場合} です

また、 picture 環境などで新たな記号を作る場合、大きさの指定に対応するための工夫については、大きさのパラメータである \tf@size,\sf@size,\ssf@size を使うのが普通だと思います。

例

\makeatletter
\def\parall{%
   \mathord{\mathchoice
      {\@pallal\tf@size}{\@pallal\tf@size}%

      {\@pallal\sf@size}{\@pallal\ssf@size}}}%
\def\@pallal#1{%
\vcenter{\hbox{%
      \dimen@#1\p@\unitlength.1\dimen@%
      \allinethickness{.05\dimen@}%
      \path(0,-2)(8,-2)(10,5)(2,5)(0,-2)%
      \vrule\@width\dimen@\@height\z@\@depth\z@%
      }}}%
\makeatother

ここで

$\textstyle{\parall BCDE}$
$\scriptstyle{\parall BCDE}$
$\scriptscriptstyle{\parall BCDE}$

の結果は少し調整が足りませんが、とりあえず BCDE

BCDE

BCDE

となります。

3.1.2 図の大きさの汎用性

図の大きさに汎用性を持たせる場合には次のようなことが考えられます。

• 大きさの指定を用紙の横幅などのパラメータから取得する

• 引数またはオプション引数で指定が可能なようにする

はじめのことはパラメータ \textwidth を使って \unitlength を指定すればよいでしょう。例えば、横に２個並列することも考えて図の大きさ（横幅）を 0.45\textwidth にしておくことなどです。また次のことも考え方は同じで、引数で指定できるようにしておけば OK です。

また図形の構成要素では、線の太さなども変化するようにしておくと便利です。先の平行四辺形の例では、そのようにしてあります。

3.2 条件分岐補筆

3.2.1 /if

\if 系のコマンドを使用する際の注意点について触れます。次の例を見てください。

例

\def\C{TRUE}
\def\D{FALSE}
\if xx\C\else\D\fi

のときこの結果は TRUE となります。また次の例では

例

\def\C{TRUE}
\def\D{FALSE}
\if xy\C\else\D\fi

のときこの結果は FALSE となります。これらは単純に続く二文字を比較してそれらの等しいかどうかを判断して条件分岐させています。ところが、続く二文字にあたるものがマクロ定義されていたらどうでしょうか？それを視るためのものが次の例です。

例

\def\A{a}
\def\B{a}
\def\C{TRUE}
\def\D{FALSE}
\if\A\B\C\else\D\fi

のときこの結果は TRUE となりますが

例

\def\A{a}
\def\B{b}
\def\C{TRUE}
\def\D{FALSE}
\if\A\B\C\else\D\fi

のときこの結果は FALSE となります。また次のように

例

\def\A{a}
\def\E{a}
\def\B{\E}
\def\C{TRUE}
\def\D{FALSE}
\if\A\B\C\else\D\fi

のときこの結果は TRUE となります。つまりマクロは２回展開されてから比較されています。さらに分類コードが異なる場合でも

例

\def\A{a}
{\catcode`\a=12\gdef\B{a}}

\def\C{TRUE}
\def\D{FALSE}
\if\A\B\C\else\D\fi

のときこの結果は TRUE となります。また

例

\def\A{ab}
\def\B{ab}
\def\C{TRUE}
\def\D{FALSE}
\if\A\B\C\else\D\fi

のときこの結果は FALSE となります。しかし

例

\def\A{aa}
\def\B{ab}
\def\C{TRUE}
\def\D{FALSE}
\if\A\B\C\else\D\fi

のときこの結果は abTRUE となります。したがって、あくまでも続く２文字の比較において、文字が等しいときに真となるということです。

また、あまり使うことはないと思いますが、比較するものが展開されない命令ならば常に真となります。

例

\def\C{TRUE}
\def\D{FALSE}
\if\let\catcode\C\else\D\fi

の結果は TRUE となります。

3.2.2 /ifx

先の \if コマンドに似ていますが異なるものです。また例で視ていくことにします。

例

\def\C{TRUE}
\def\D{FALSE}
\ifx xx \C\else\D\fi

例

\def\C{TRUE}
\def\D{FALSE}
\ifx xy \C\else\D\fi

のときこの結果は FALSE となります。この場合は \if と同じです。さらに次の例を視ます。

例

\def\A{a}
{\catcode`\a=12\gdef\B{a}}
\def\C{TRUE}
\def\D{FALSE}
\ifx\A\B\C\else\D\fi

のときこの結果は FALSE となります。つまりこの場合は分類コードも同じでないと真とはなりません。また

例

\def\A{ab}
\def\B{ab}
\def\C{TRUE}
\def\D{FALSE}
\ifx\A\B\C\else\D\fi

のときこの結果は TRUE となります。しかし

例

\def\A{aa}
\def\B{ab}
\def\C{TRUE}
\def\D{FALSE}
\ifx\A\B\C\else\D\fi

のときこの結果は FALSE となります。この場合には \if とは違ってきちんと二文字づつ比較されていることがわかります。ところが

例

\def\A{ab}
\def\E{ab}
\def\B{\E}
\def\C{TRUE}

\def\D{FALSE}
\ifx\A\B\C\else\D\fi

のときこの結果は FALSE となります。これは、比較の際にマクロが一度しか展開されないためです。このように最終的には同じになるのに、展開の回数によって左右されることがあるものには注意が必要です。

3.3 おまけ

3.3.1 ￥記号 10 様

円記号を作るマクロを集めてみました。

\def\yen{{Y\kern-7.5pt=}}
\def\yen{\makebox[0pt][l]{Y}=}
\def\yen{\leavevmode\hbox to 0pt{Y\hss}=}
\def\yen{\leavevmode\rlap{Y}=}
\def\yen{Y\hbox to 0pt{\hss=}}
\def\yen{Y\llap{=}}
\def\yen{{\ooalign{\hfill Y\hfill\crcr\hfill =\hfill}}}
\def\yen{{\ooalign{Y\crcr\hss=\hss}}}
\def\yen{\leavevmode\vbox to 3.5pt{\hbox{=}\vss\hbox{Y}}}
\def\yen{\leavevmode\vbox{\baselineskip 0pt\lineskip -.9ex{%
         \ialign{##\crcr\hfill Y\hfill\crcr\hfill =\hfill\crcr}}}}

上から出力はそれぞれ Y = Y = Y = Y = Y = Y = Y = Y = = Y Y = となります。ほとんどは「磯崎」本のパクリですが、そうでないものもあります。 \kern で位置

調整しているものは、フォント等が変わると使えませんので若干汎用性には欠けます。最後の二つは強引に作ったものです。わざわざ縦並べを考えてずらしてあります。

マクロで記号などを新たに作る場合に、結構重ね合わせというテクニックを使いますが、その際に重要になるのが box 関係のコマンドです。 \vbox, \hbox それぞれに使う上でのノウハウがあるようです。上記の 10 例を参考にして box の復習をされるのも良いかも知れません。

尚、単に円記号が使いたいだけなら、マクロ定義しなくても ascmac を使うことで \yen は使用可能です。

4 おわりに

4.1 あとがき

前編から、数値計算のところだけでもまとめておかなければならないという自分自身への義務感にかられて、とりあえずまとめたのがこの続編です。本来ならばもっといろいろなテーマに、例えば、条件判断の使用例の詳細やトークンなどにも触れなければいけなかったのでしょうが、そこは著者の力量不足ですぐには無理です。そこで数値計算に的を絞って過去のマクロ作製時にいろいろ試しながら貯めておいた屑マクロを例に示しながらまとめました。そこに汎用性のところと条件分岐で著者自身が気になった \if,\ifx の違いの部分の補筆を加えたものがこれです。非常に不正確な部分も多いのでしょうが現状ではこれが限界です。

さて、これに続く中級編ですが、この予定はいまのところありません。備忘録というのはいろいろやって、そのメモをまとめるものでしょうが、もうまとめる肝腎のネタがほとんどありません。ニフティの TEX フォーラムなどで話題をもらえるとも聞いたのですが、ニフティなんて入会の仕方すら知りません（ははははは！）。また、 HP 上で手に入るマクロに関するオンラインテキストも存在したらしいのですが、現在ではもう入手できないようです（誰か譲ってください！）。そうした現状ですから続編の予定は無いのです。悪しからずご了承ください。