* 基礎知識 [#s5fc1cf9]
[[TeX入門]] /
マクロの作成

----


* マクロの作成 [#nf5fd4d9]

TeX の特徴の一つにマクロが作成できることが挙げられます。
マクロを活用することによって、ミスの少ない仕上がりや作業効率の向上などの効果が期待できます。
また、実用的な面を持つだけではなく、知的な趣味としても愉しむことができます。
TeX マクロは実用的な面を持つだけではなく,知的な趣味としても愉しむことができます。
LaTeX で簡単なマクロを作成したい場合は [[LaTeX入門/LaTeXマクロの作成]] を参照してください。
こちらでは TeX に踏み込んだ解説を目的としています。

#contents

// 以下は手を付けていません。

* 基礎知識 [#s5fc1cf9]

マクロの作成技術を身につけるにあたって必要な基本知識を列挙しておきましょう。
これらの事柄を調べてゆくと自ずとマクロ作成技術が身に付くことでしょう。

参考書について:マクロを作成する上で必要となる TeX のプリミティブ命令の多くは、LaTeX の入門レベルの解説書では触れられていないことが多いです。『TeXブック』には当然解説されていますが、入手は困難なようです。
とりあえず,この Wiki の“[[TeXの本]]”の項で挙げられているものを参考になさってください.
参考書について:マクロを作成する上で必要となる TeX のプリミティブ命令の多くは,LaTeX の入門レベルの解説書では触れられていないことが多いです。
『TeXブック』には当然解説されていますが,日本語版の入手は困難です。
とりあえず,この Wiki の [[TeXの本]]の項で挙げられているもの(TeX by Topic や TeX Reference Manual が詳しいです)を参考になさってください.

- トークン (文字トークンとコントロールシークエンス(コントロールワード/コントロールシンボル))
- カテゴリーコード (\catcode, \makeatletter, \sanitize)
- 基本レジスタ (\count, \dimen, \skip/\muskip, \box, \toks, 数値と数字の違い)
- 定義と代入 (\def, \let, \newcommand, \DeclareRobustCommand)
- グルーピング ({, }, \bgroup, \egroup, \begingroup, \endgroup)
- 条件分岐 (\if, \ifx, などの各種 \if)
- 展開の制御 (\expandafter, \edef, \noexpand, \afterassignment)
// \aftergroup は有効な使用例が少ないため,保留(ただし,color パッケージで
// きわめて効果的に用いられています).
- トークンの制御 (\the, \string, \csname, 空白トークン)
- ファイル入出力(\openin/\closein, \read, \openout/\closeout, \write,
\immediate)
- デバッグ (\show, \showthe, \meaning, プリミティブとマクロ)
- 組版上の問題に由来する処理(水平モード/垂直モード, \par, \halign/\valign, \mark などの,
一般的なプログラミングの話では出てこない処理を扱うプリミティブ)
// これは,“基本知識”として挙げるべきかどうかは微妙.
// また,1 項目にしてしまうのは乱暴かもしれません.
- LaTeX における慣用的な処理(\@elt を用いたリストの処理や,
\@testopt 等の常用される内部処理用マクロの用法)
- そのほか融合問題,分類が困難な問題
// 問題カテゴリを追加してみました
- (あと、どうしましょう?)
- (あと,どうしましょう?)

* 解説 [#i84d9f01]
(注意)この節の内容には,初学者にとっての理解のしやすさを優先するため,不正確な記述が含まれています。従って,リファレンスマニュアルとしての使用に堪えるものとはなっていません。

** トークン [#t258c07c]
TeX が読み込むファイルはテキストファイルであり,文字コードの羅列です。
TeX はそこから様々な命令を読み取って動作します。
例えば入力ファイルに “\sqrt{2}” とあれば,“\sqrt” が平方根を組み立てる命令であることを読み取って,根号の中に2を収めたものを出力します。
この際 “\sqrt” は “\”, “s”, “q”, “r”, “t” という5文字の羅列ではなく “\sqrt” という一塊のものとして認識されます。
この,TeX にとって意味のある,それ以上分解できない一塊のものが''トークン''です。
前述の “\sqrt{2}” であれば,TeX には “\sqrt”, “{”, “2”, “}” という4つのトークンとして把握される(文字列をトークンに変換している)ことになります。

トークンには,単独の文字がそのままトークンとなっている''文字トークン''と,sqrt のような名前によって区別されるトークンである''コントロールシークエンストークン''があります。
コントロールシークエンストークンのことを単に''コントロールシークエンス''ともいいます。
このような解説文でコントロールシークエンスを記述する場合,例えば『TeXbook』などでは四角囲みの中にトークン名を収めて表しています。
ここでは括弧で括って[sqrt]のように表してもいいかもしれません(ソースファイル中の“\sqrt”という文字列に対応するコントロールシークエンストークンの名前は“sqrt”であると考えます)。

文字コードの羅列をトークンに変換してゆくプロセスは概ね次の規則に従います。
+ “\” があれば続く文字列から名前を読み取ってコントロールシークエンスに変換する。この際
++ “\”に続くのが英文字であれば,さらに続く英文字を取れるだけとったものをそのコントロールシークエンスの名前とする
// 空白のスキップにふれるべき?
//// サブセクションで解説してみます。
++ “\” に続くのが英文字でなければ,“\” の後に続くその1文字をそのコントロールシークエンスの名前とする
+ “\” でなければ,その1文字を単独の文字トークンとして読み取る

ここで「英文字」とは何かという問題がありますが,これについては次項「[[カテゴリーコード>TeX入門/マクロの作成#mef7a198]]」を参照してください。
ただし,ここでは pTeX で使える日本語を含むコントロールシークエンストークンは考えません.

コントロールシークエンスには二種類存在します.
ひとつは上記の1のiに相当する,“\”のあとに英文字が続くものでこれをコントロールワードといいます.
例えば,“\alpha”によって生成される[alpha]はコントロールワードです.
もうひとつは上記の1のiiに相当する,“\”のあとに英文字以外の1文字が続くもので,これをコントロールシンボルといいます.
例えば,\!によって生成される[!]はコントロールシンボルです.

(注意)上の規則で“\”という文字を使いましたが,より正確には,カテゴリーコードが0である文字といったほうがよいでしょう。カテゴリーコードについては後の解説を参照してください。

*** トークンの区切りと空白文字の読み飛ばし [#ta414729]

さて,ここでコントロールワード[small]に続いて英文字の文字トークン“a”を置くことを考えて見ましょう。
本文中で小さな文字を使って“a”という活字を印字したいという場面です。

ソースファイルにはどう記述すべきでしょうか?
“\smalla”でしょうか?
これでは駄目ですね。
上記の規則 1のi によって続く限りの英文字が取られて[smalla]というコントロールワードになってしまい,意図とは違ってしまいます。
では英文字以外のものを“\small”の後におけばよいのですから“\small:a”などとしてみます。
今度は[small],“:”,“a”となってしまい間に余計な文字トークンが入ってしまいます。

このように,コントロールワードに続けて英文字トークンを置きたい場合にはなにか区切りになるものが必要ですが,その区切り自体が余計なトークンになってしまうなら,困る場合も出てきます。
そこで,区切り文字として空白文字を使った場合には例外的に,コントロールワードの名前の終わりを表す区切りとして認識したあとで,その空白文字を読み飛ばします。

この例外規則のおかげで,先ほどの問題は“\small a”と入力することで解決されるわけです。
この記述から生成されるトークンは,[small], “ ”, “a”ではなくて,[small], “a”となります。

空白文字の読み飛ばしについては,他にも考慮すべき例外ルールがあります。

** カテゴリーコード [#mef7a198]

前節で触れた,「英文字」とは何か,という問題に答えるのがこの節です。

TeX で処理するソースファイルはテキストファイルで,われわれの目には文字列のように見えていますが,その実体は文字コードの羅列です。
一文字に8ビットのコードを割り当てるシステムでは文字コードは0から255までの数です。
例えば“a”という文字の文字コードは97となっています。

TeXではこれらの文字を「英文字」や「空白文字」などに分類して,その分類を動的に変えられるようになっています。
そのための仕組みが''カテゴリコード''です。

例えば,特に変わったことをしなければ,大文字の“A”から“Z”までと小文字の“a”から“z”までの計52文字だけが「英文字」なので,ソースファイルの“\hoge@hoge”という文字列を TeX が読み込むとき,前節のトークン化の規則によって,この文字列は[hoge]というコントロールシークエンスとそれに続く5個の文字トークン“@”, “h”, “o”, “g”, “e”として読み込まれます。
ところが文字の分類を動的に変えられるという TeX の仕組みを利用して,“@”という文字を「英文字」と見なすように設定しておけば,同じ“\hoge@hoge”という文字列から,[hoge@hoge]というたった一つのコントロールシークエンスが読み取られることになるわけです。(下の小節「[[コントロールシークエンス名に“@”を織り交ぜたもの>TeX入門/マクロの作成#f8b87eec]]」も参照)

さて,TeX はこのように文字の分類をしているわけですが,TeX はコンピュータプログラムなので,「英文字」とか「空白文字」という概念を理解しているわけではなくて,単に11番目のカテゴリーだとか5番目のカテゴリーだとか把握しているのです。
例えば「“a”は英文字だ」という代わりに「文字コード97の文字は11番目のカテゴリーの文字だ」という具合です。
TeX はある文字コードの文字がどの分類に属するかを記憶しているわけです。

ここで TeX による文字の分類を一覧表にしてみましょう。

|カテゴリーコード|分類|通常この分類に属する文字|h
|0|エスケープ文字|\|
|1|グループ開始文字|{|
|2|グループ終了文字|}|
|3|数式モードへの移行文字|$|
|4|アラインメントタブ|&|
|5|行の終了文字|文字コード13の文字|
|6|パラメータ文字|#|
|7|上付き文字|^|
|8|下付き文字|_|
|9|無視する文字|文字コード0の文字|
|10|空白文字|文字コード32の文字|
|11|英文字|AからZまでおよびaからzまで|
|12|その他の文字|!"'()*+,-./0123456789:;<=>?@[]`他1文字|
|13|アクティブ文字|&tilde;|
|14|コメント文字|%|
|15|無効文字|文字コード127の文字|

// 上の表は,plain TeX における設定に基づいたものと思われます.
// 一方,制御文字のカテゴリーコードについては,
// plain TeX での設定と LaTeX での設定の間に相違があります.
// LaTeX のデフォルトでは,文字コード 0 から 31 までおよび 127 の制御文字に
// ついては次の 4 個が例外で,それ以外はカテゴリーコード 15 となっています.
// 文字コード  9(horizontal tab,^^I): カテゴリーコード 10
// 文字コード 10(line feed,^^J):      カテゴリーコード 12
// 文字コード 12(form feed,^^L):      カテゴリーコード 13
//                                        \outer\def^^L{\par}
// 文字コード 13(carriage return,^^M):カテゴリーコード  5
// なお,これらの例外については,plain TeX でも同じ設定となっています.

TeX がテキストファイルから文字コードの羅列を読み込んでトークンに変換していくとき,カテゴリーコードが0か否か,および11か否かということは特別な意味を持ちます。
カテゴリーコードが0の文字はコントロールシークエンスの始まりを表し,その後にカテゴリーコード11の文字が続く限りそれがコントロールシークエンスの名前になるからです。
その他のカテゴリーの文字は単独の文字トークンとなるわけですが,このとき,その文字トークンには対応するカテゴリーコード付与されます。

***カテゴリーコードへのアクセス [#c853d199]

文字の分類を変えるには \catcode というプリミティブ命令を使います。
例えば“a”という文字の分類を「英文字」から「その他の文字」へ変更するには,“a”の文字コードが97で,「その他の文字」のカテゴリーコードが12なので
 \catcode97=12
のようにします。
このように変更した後では,例えば“\small”という文字列を TeX がソースファイルから読み込むとき,[small]というコントロールシークエンスではなくて,[sm]というコントロールシークエンスに続いて“a”, “l”, “l”という 3 個の文字トークンが続いたものとして読み取られることになります。

(今日はとりあえずここまで。続きはいつになるか分かりません。)

***コントロールシークエンス名に“@”を織り交ぜたもの [#f8b87eec]

少し上のところで“\hoge@hoge”という文字列の例を紹介しました。
通常のカテゴリーコード設定の下では、“@”は英文字の一員ではないため、この文字列“\hoge@hoge”は [hoge],“@”,“h”,“o”,“g”,“e”という6個のトークンとして読み取られるのでしたが、“@”のカテゴリーコードを英文字に変更することで [hoge@hoge] という単一のトークンとして読み取らせることができるという例でした。
“@”の文字コードは64ですから、“@”を英文字として扱うためには \catcode64=11 と指定すればよいことになります。
この作業はたびたび必要になるので後述するようなマクロ定義による省略形が用意されています。
\makeatletter という命令で“@”のカテゴリーコードを11(英文字)にして、\makeatother という命令で“@”のカテゴリーコードを12(その他の文字)に戻します。
TeX や LaTeX では、内部命令をユーザーの不用意な再定義から保護する仕組みとして、この“@”の振る舞いを利用しています。
後述するように、TeX や LaTeX では、ユーザーがほぼすべての命令をマクロとして自由に定義し直すことができてしまいます。
この自由度の高さゆえに、内部で使われている需要な命令の定義をユーザーが意図せず変更してしまうことが起こり得ます。
そこで、内部で機能する命令の名称は \hoge@hoge のように英文字化した“@”を含むものとして定義しておいて、ユーザーの文書を処理する際は“@”のカテゴリーコードを「その他の文字」になるように戻しておくことで、不用意に内部命令にアクセスしたり定義し直したりすることを防いでいるというわけです。
内部命令について詳しく知ったうえであえて動作を変更しようとするときは、\makeatletter によって一時的に“@”を英文字扱いとしてから内部命令の定義を変更したりした後で、\makeatother で“@”を「その他の文字」に戻すようにします。

** 基本レジスタ [#i41b7d06]

TeX には、次の表に示す種類ごとに256個のレジスタ(変数)があります。

|レジスタの種類|アクセス|値|値の設定|h
|整数レジスタ|\count0 ~ \count255|符号付32ビット整数値( -2147483648 ~ 2147483647)|<整数レジスタ>=<数値>|
|長さレジスタ|\dimen0 ~ \dimen255|長さ(-16383.99998pt ~ 16383.99998pt=1073741823sp)|<長さレジスタ>=<長さ>|
|グル―レジスタ|\skip0 ~ \skip255|伸長度と収縮度を持つ長さ(10pt plus 5pt minus 1pt など)|<グル―レジスタ>=<長さ> plus <伸長度> minus <収縮度>|
|ボックスレジスタ|\box0 ~ \box255|水平ボックスや垂直ボックスとなる|\setbox<レジスタ番号>=\hbox{...} など。\hbox の代わりに \vbox, \vtopなども可|
|トークンリストレジスタ|\toks0 ~ \toks255|トークンの列|<トークンリストレジスタ>={...}|

レジスタに値を設定するには \count0=32 とか \dimen1=24pt のように <レジスタ>=<数値や長さ> と指示します。
この代入に使うイコール“=”は文脈によっては省略可能で、\count0=\count1 のかわりに \count0\count1 などと書くことができます。

長さの単位は 72.27pt = 1in = 25.4mm などが使われます。
pt(ポイント)は一般的な定義よりわずかに小さくなっています。
sp(スケールドポイント)という単位は 2の16乗分の1(=0.0000152587890625) pt で、TeX における長さの基本単位です。
長さの値は TeX 内部で整数値として保持されていて、整数が要求される文脈ではそのまま整数として使われ、
長さが要求される文脈では sp 単位の長さとして解釈されます。
例えば \dimen0 が 1pt であるとき、\count0=\dimen0 のように整数レジスタに長さを代入すると、\count0 の値は 65536 となります。

*** 数値の表現 [#c479ca64]

(ちょっと説明が面倒なので、保留 → どなたかへ)

*** レジスタの演算 [#caec7e39]

|演算|記し方|h
|加法|\advance<レジスタ> by <数値や長さ>|
|減法|\advance<レジスタ> by <負の数値や長さ>|
|乗法|\multiply<レジスタ> by <数値>|
|除法|\divide<レジスタ> by <数値>|

どの演算も<レジスタ>のところに指定したレジスタに演算がなされて、その<レジスタ>の値が更新されます。
文脈によって“by”は省略可能です。

*** レジスタの割り当て [#had0fdbf]

TeX の各種レジスタには 0 番から 255 番までのレジスタ番号でアクセスできますが、
複雑なマクロを組むときには、レジスタごとの役割を表すレジスタ名を付けることができれば便利です。

TeXでは \countdef<トークン>=<レジスタ番号> と指示することで、<トークン>が整数レジスタ代わりに使えるようになります。
(例:\countdef\cntA=64 とすると、\cntA が \count64 の代わりに使えるようになる)
この指示には、レジスタの種類に応じて \countdef, \dimendef, \skipdef, \boxdef, \toksdef を使います。

ただし、この例のように \cntA を \count64 に割り当てたとしても、
それを知らない他人が作ったマクロ内部で \count64 の値を変更するような処理があれば、
\cntA でアクセスする値が知らないうちに変えられてしまいます。
これでは他人が作ったマクロを組み合わせて使うときに困るので、plain TeX や LaTeX では統一的にレジスタを割り当てる仕組みが
(これまたマクロによって)実装されています。

この仕組みのもとでは、\newcount<トークン> と指示するとレジスタ番号の若い方から順に整数レジスタを割り当てて、<トークン>がそのレジスタ代わりに使えるようになります。割り当てられたレジスタのレジスタ番号は plain TeX や LaTeX の内部に保持されているので、何番レジスタに割り当てられたかは分かりませんが、気にせずに使えるようになります。
この割り当てには、レジスタの種類に応じて \newcount, \newdimen, \newskip, \newbox, \newtoks を使います。

plain TeX や LaTeX でマクロを組む場合、このように \newcount などで割り当てられたレジスタのみを使うようにして、直接レジスタ番号を指定した \count64 のような使い方はしないようにしています。これによって、様々な人が作成したマクロを組み合わせて使えるようになっています。

** 定義と代入 [#v38e683c]

マクロの定義のしかたです。
ここの解説を読む前に,トークンについて理解しておくとよいでしょう。
上のほうの解説がまだなら先にそちらをお読みください。

*** 引数を取らない簡単な置き換えマクロ [#e7dd9b15]

一般に、プログラムソース中に命令やトークンから成る特定の並びが何度も現れるとき、その並びに短い名前を付けて管理する仕組みをマクロといいます。ソースファイル内に、その特定の並びの代わりに短い名前を書いておくと、プログラムの実行中や前処理の段階で本来の並びに置き換えて処理されるので、ソースファイルを簡略化するのに使われます。マクロ機能を有するプログラム言語は多くあり、マクロ機能の詳細は、言語ごとに様々です。

TeXのマクロ定義の基本は,引数を取らない簡単な置き換えマクロで,次のように定義します。
 \def<トークン>{置き換えテキスト}
ここで,<トークン>のところには定義しようとするコントロールシークエンスかアクティブ文字を書きます。
例えば,TeX のロゴマークを出力する命令である \TeX は、マクロとして次のように定義されています。
 \def\TeX{T\kern -.1667em\lower .5ex\hbox {E}\kern -.125emX}
このようにすると,\TeX というコントロールシークエンスは
“T\kern -.1667em\lower .5ex\hbox {E}\kern -.125emX”というトークンの並びに展開されるマクロとして定義されて,これ以降,\TeX が展開されるたびに,
“T\kern -.1667em\lower .5ex\hbox {E}\kern -.125emX”に置き換えられて処理されます。
これは,“T”に続けて0.1667emの長さの分だけ左に詰めて,0.5exという長さの分だけ下に下げたところに“E”を置き,それに続けて0.125emだけ左に詰めて“X”を置くという動作をさせるもので,“TeX”のロゴを文書中に表現するものです。
文書中に TeX のロゴが何度出てくるような場合,そのたびにこの長い命令を入力するのは大変ですから,マクロを定義することによって簡単に \TeX と入力して済ませられるようになるわけです。

このような組版上の命令ではなくても,
 \def\ABP{Alexandroff-Bakelman-Pucciの不等式}
のように定義しておけば,長い名前を \ABP と簡単に入力できるようになりますし,タイプミスを防ぐのにも役立ちます。

*** マクロとプリミティブ、展開と実行 [#u493785c]
// この項、ここ以外にふさわしい場所があるかもしれません。
// プリミティブのうちでも \if*** のように展開可能なものがあって \csname の中で使えたりする、ということを説明するのに、“展開”と“実行”についてどこかで説明が必要と考えました。

ユーザーが定義する命令をマクロというのに対して、もともとTeXに備わっている命令はプリミティブ(=“原始的な組版命令”)といいます。

TeX 実行中に、マクロがマクロ定義に従って対応するトークンの並びに置き換えられることを“展開”といいます。典型的なマクロは、より長いトークン列に置き換えられるので、その置き換えられる様子を“展開”といい表すわけですが、それに止まらず、マクロと引数(引数については次項参照)からなる長いトークン列がより短いトークン列や空のトークン列に置き換えられる場合や、マクロ以外のプリミティブ命令の一部が別のトークン列に置き換えられる場合も含めて、トークン列の変換の様子を“展開”といいます。トークン列の変換を表す“展開”に対して、TeXが内部のレジスタ(変数)の値を変更したり、組み立て中の組版リストに文字を付け加えたり、現在の組版モード(水平モード、数式モードなど)を変更したりといった、TeXがプリミティブ命令を処理して動作を進めることを、命令を“実行”するといいます。

TeXが動作しているとき、マクロはまず展開され、展開され尽くしてできたプリミティブは“展開”または“実行”されます.TeX の動作を考えるときには、この“展開”と“実行”を区別することが肝要です。

*** 引数を取るマクロ [#ub81277c]

マクロには、実行時に引数に応じて動作を変えるようなものもあります。
多くのプログラミング言語では引数を指定するには括弧とカンマを用いて macro("test",2) のような具合に書きますが、TeX の場合は引数の与え方が全く異なるので、先入観を捨てておかないと理解しづらいでしょう。


TeX で単純な引数を取るマクロを定義するには、次のように記述します。
 \def<トークン>#1#2#3{置き換えテキスト ― この中で仮引数として #1,#2,...,#9 が使える}
ここで,<トークン>は定義しようとするコントロールシークエンスかアクティブ文字です。続く #1#2#3 の部分はいくつの引数を取るかを示すもので、#9 までの 9個以内で必要な分だけつなげて書きます。
引数の番号は1から順に書いていきます。上の例は 3個の引数を取る場合です。
マクロが展開されるときには、ブレイス{}で囲まれたテキストか、そうでなければトークンが引数として読み込まれて、置き換えテキストの中の #1 などのところにはめ込まれます。

例えば、数値の指数表現としてアボガドロ定数を$6.02\times 10^{23}$のように書くとき、\times や 10^ の部分は決まりきった表現なので省略したいとしましょう。
このとき、
  \def\N#1#2{#1\times10^{#2}}
のようなマクロ \N を定義しておけば、「アボガドロ定数は$\N{6.02}{23}$とする」のように使えるわけです。
マクロが TeX によって展開されると \N{6.02}{23} の部分は 6.02\times10^{23} に置き換えられます。
ここで例えば定義のブレイスを一組忘れて \def\N#1#2{#1\times10^#2} のようにしたとすると、\N{6.02}{23} の展開結果は 6.02\times10^23 となってしまい、10 の肩に 2 だけが乗せられたあとで 3 が 10 と同じ大きさで出力されてしまうことになります。
また例えば最初の定義のまま使うときにブレイスでなくパーレン \N(6.02)(23) を使ってしまうと、「\N(6」までがマクロの引数と見なされて「(\times10^{6}」と展開されて、そのあとに未処理の「.02)(23)」が続くことになります。

マクロの引数の形式には上に挙げた単純な引数の他に区切り付き引数と呼ばれるものもあります。
(どなたかお願いします。)

** グルーピング [#cf2ee4db]

グルーピングにより,様々な物事が「ローカル」になります.グルーピングを生み出す最も典型的な方法が
  {<グルーピングの中身>}
と {} で囲むことです.(より正確には,カテゴリーコード1の文字と,カテゴリーコード2の文字で囲むことです.)この中での代入はローカルになります.たとえば

  \def\test{A}
  {
    \def\test{X}
    \test % -> Xと展開される
  }
  \test % -> Aと展開される

となります.{ により新しいグループへと入り,その中で定義された \test は } によりグループを脱出した際にもとの定義に戻されます.

ただし,\global が前置してある場合,その定義は「グローバル」になります.たとえば

  \def\test{A}
  {
    \global\def\test{X}
    \test % -> Xと展開される
  }
  \test % -> Xと展開される

となります.\global\def の短縮形として \gdef が存在します.また,パラメータ \globaldefs が正の場合,全ての定義などはグローバルになります.(通常の状態では \globaldefs は0です.)

ローカルになるのは \def によるマクロ定義のみではなく,レジスタへの代入も含まれます.

  \count0=1
  {
    \count0=2
    % ここでは\count0=2
  }
  % ここでは\count0=1に戻る

ただし,\hyphenation のように常にグローバルになるようなものも存在します.

*** グルーピングを発生させるトークン [#n4769805]
既に述べた通り,グルーピングを生み出す最も典型的な方法は {} で囲むことですが,これはカテゴリーコードがそれぞれ1,2の文字ならば何でも良いですし,{ に対して } が対応している必要もありません.たとえば

  \def\test{A}
  {
    \catcode78=2 % N のカテゴリーコードを 2 に変更
    \def\test{X}
    \test % -> Xと展開される
  N% グルーピングが終わる
  \test % -> Aと展開される
  N% グルーピングの終了とともに N のカテゴリーコードも戻るため,これは普通の N

とすることもできます.またこれらの文字に \let されているトークンでも同じです.plain TeX や LaTeX のデフォルトでは

  \let\bgroup={
  \let\egroup=}

とされているため,

  \def\test{A}
  \bgroup
    \def\test{X}
    \test % -> Xと展開される
  \egroup
  \test % -> Aと展開される

というようにもできます.

プリミティブ \begingroup と \endgroup もグルーピングを発生させます.\begingroup で開いたグループは \endgroup で閉じる必要があります.グルーピングは入れ子になっている必要があるため,

 { \begingroup } \endgroup

とするとエラーになります.

*** 引数の範囲を示すグルーピング [#yf516438]
グルーピングのもう一つの役割が,引数の範囲を示すことです.たとえば,LaTeX において定義されている \pagestyle マクロは

  \pagestyle{plain}

のように使用されますが,ここでの {} によるグルーピングは \pagestyle マクロに与える引数を表します.
このような引数の範囲を示すグルーピングには,多くの場合にカテゴリーコード1,2の文字そのものしか使えません.たとえば

  \pagestyle\bgroup plain\egroup

とするとエラーになります.
このことを逆に使うと,次のようなことが可能です.

  \def\testA{\begingroup}
  \def\testB{\endgroup}
  \testA
  % ここは\begingroup,\endgroupによるグルーピングの内部
  \testB

\begingroupや\endgroupの代わりに {} と書くと,\defの定義本体の終わり等を意味してしまうことに注意します.
LaTeX における環境内はグルーピングされていますが,これは \begin/\end 内に \begingroup/\endgroup を仕込むことで行われています.

(マスターカウンタとバランスカウンタの話?)


** 条件分岐 [#u303eedc]
TeX における条件分岐は,他のプログラミング言語の条件分岐とはまったく異なるものです。
先入観を持っていると混乱するでしょう。
多くのプログラミング言語では条件分岐のための if 文というものが用意されています。
if 文は,論理演算子を組み合わせた論理式の真偽値を算出して,それに応じて処理を分岐します。
ところが TeX には論理式はおろか論理演算子というようなものすらもありません。
TeX で分岐のために扱える条件は,現在の TeX の状態を問い合わせるものや,二つのトークンが同じものかどうか比較するものなど,ごく限られたものしかありません。
//(この段階では詳しすぎる内容のためコメントアウト)さらに,条件分岐の際に TeX がする動作というものは,条件に応じて処理を分岐するのではなく,条件に応じて実行する必要がなくなった部分を読み飛ばすに過ぎません。

まず基本的な例を見てみましょう。
//最初の例として \if を挙げないのは,トークンについての理解が不可欠なのと,他のプログラミング言語における if についての先入観を招きそうだと考えたためです。
 \ifmmode P\else $P$\fi
この例は,“P”という文字をいつでも数式イタリック体で印字しようというものです。
そのためには,TeX が現在数式モードにあるならそのまま P を印字させ,数式モードになっていなければ $ によって数式モードに移行してから P を印字させたあとで $ によってもとのモードに復帰させればよいでしょう。
さて上記の命令は TeX に次のようなトークンの列として読み込まれます。
 [ifmmode],“P”,[else],“$”,“P”,“$”,[fi]
[ifmmode],[else],[fi]の三つのコントロールシークエンストークンは TeX のプリミティブ命令です。
まず[ifmmode]によって,TeXは現在のモードが数式モードであるかどうかを調べます(if math-mode という名前から推察されるとおりです)。
もしも数式モードならば,[else]や[fi]を見つけるまではそのまま処理を続けます。
この状態で[else]を見つけたならば,それ以降は[fi]を見つけるまでひとつひとつのトークンを読み飛ばしてゆきます。
[else]があってもなくても,[fi]を見つけたところでこの条件分岐は終了して,TeX はそのあとに続く処理を続行します。
“fi”というのは“if”の逆さつづりで,開き括弧と閉じ括弧が左右逆向きになっているのを連想させるようなしゃれでしょう。
fi という英単語があるというわけではないようです。
今度は,[ifmmode]のところで TeX の現在のモードが数式モードでなかった場合を考えましょう。
このとき TeX は[ifmmode]のあとに続くトークンを[else]や[fi]を見つけるまでひとつずつ読み飛ばしていきます。
この状態で[else]を見つけたならば,読み飛ばすのは止めにして[else]のあとに続くトークンに従って処理を続けてゆきます。
[else]があってもなくても,最終的に[fi]を見つけたところでやはりこの条件分岐は終了して,TeX はそのあとに続く処理を続行します。

TeX の条件分岐処理は,上の例で[ifmmode]が担っていた条件判断の部分に何種類かのプリミティブ命令が用意されているだけで,あとのトークンの読み飛ばし方や,[else]や[fi]の扱いについては同じです。
\ifmmode の代わりに使える条件分岐命令を列挙してみましょう。
|\ifmmode|現在のモードが数式モードかどうか|
|\ifhmode|現在のモードが水平モードかどうか|
|\ifx<トークン1><トークン2>|<トークン1>と<トークン2>が同じトークンかどうか。&br; - 文字トークンの場合は,文字コードもカテゴリーコードも一致するか&br; - コントロールシークエンストークンの場合は,意味が一致するか(名前は違ってもよい)|
|\if<文字トークン1><文字トークン2>|<文字トークン1>と<文字トークン2>の文字コードが一致するかどうか|
|\ifcat<文字トークン1><文字トークン2>|<文字トークン1>と<文字トークン2>のカテゴリーコードが一致するかどうか|
|\ifodd<数値>|<数値>が奇数かどうか|
|\ifnum<数値に関する等式や不等式>|等式や不等式が成り立つかどうか|
|\ifdim<長さに関する等式や不等式>|等式や不等式が成り立つかどうか|
|\iftrue|常に真と判断される|
|\iffalse|常に偽と判断される|
|etc.||

** 展開の制御 [#na8d9f89]
各トークン列の実行は,原則として先頭から行われていきます。いくつかのプリミティブはこの展開順序を変更します.

*** \expandafter [#nf0b9376]
\expandafterは,次に続くトークンの展開/実行を抑制し,その次のトークンを先に展開する,という働きをします.例を見てみます.

 \def\testA{{A}{B}}
 \def\testB#1{[#1]}

まずは\testB\testAとした場合を考えてみましょう。まず\testBが展開されます。このマクロは引数を一つとり,今の場合は#1 = \testAですから,その展開結果は[\testA]となります。そして\testAが展開され,[{A}{B}]となります。最終的な出力は [AB] となります。

一方,\expandafter\testB\testAとしてみます。まず\expandafterが展開され,\testBの展開が抑制されます。その結果先に\testAが展開され,\testB{A}{B}となります。その後\testBが展開されます。今回は#1={A}となり,結局[A]Bと展開されます。

\expandafter自身も\expandafterの対象となります。例えば

 \def\testA{{A}{B}}
 \def\testB#1{[#1]}
 \def\testC{\testB\testA}
 \expandafter\expandafter\testC

を考えてみます。まず最初の\expandafterにより次の\expandafterの展開が抑制され,その次の\testCが展開されます。その結果展開列は\expandafter\testB\testAとなります。上でみたように,全体の展開結果は[A]Bとなります。

いくつか例を見てみましょう。

 \expandafter\def\expandafter\test\expandafter{\test,ABCDE}

最初の\expandafterで\defが抑制されます。その後二番目の\expandafterが展開され,\testの展開が抑制されます。更に{が抑制され,\testが展開されます。その後抑制されていた\def\test{が展開され,結局

 \def\test{<\testの展開結果>,ABCDE}

となります。例えば \test をカンマ区切りのリストとして使っているとすると,最後に ABCDE を加えるという操作に相当します。

なお,\expandafter が一切ない \def\test{\test,ABCDE} だとどうなるでしょうか。これにより定義された\testを展開してみましょう.\test の展開結果は \test,ABCDE となります。展開可能なトークン\testが先頭にあるので,TeX は更にこれを展開しようとし,\test,ABCDE,ABCDEとなります。以下無限に続き,最終的に TeX は TeX capacity exceeded というエラーを出して終了してしまいます。

 \def\test#1{\ifx#1.\else 0\expandafter\test\fi}

ピリオドで終わる文字列を与えると,その数だけ0を出力するマクロです.\test TeX. の展開の様子を見てみましょう.まず

 \test TeX. → \ifx T.\else 0\expandafter\test\fi eX. → 0\expandafter\test\fi eX.

となります.ここで \expandafter により \test の展開が抑制され,先に \fi が展開された結果,0\test eX. となります.以下再帰的に文字数の分だけ 0 を出力します.ここでもし \expandafter がなければ,

 0\test\fi eX.

の段階で「\test\fi」が展開され,

 0\ifx\fi.\else 0\test\fi eX

となります.これは期待した結果ではないでしょう.(更にここから \test\fi が展開されていくため,最終的には TeX capacity exceeded により終了します.)


*** \edef [#g0902f79]
\edefは\defと同様にマクロを定義しますが,定義の際に置き換えテキストを可能な限り展開する点が異なります.例えば
 \def\testA{test}
 \edef\testB{\testA}
とすると,\edefはまず置き換えテキストである\testAを展開します.その展開結果はtestですから,これは
 \def\testB{test}
と同等の働きをします.

展開ができないプリミティブに関してはそのままになります.実行がされることもありません.例えば,
 \edef\testA{\def\test{test}}
を考えてみます.\test は定義されていないとしましょう.置き換えテキスト「\def\test{test}」の展開は次のように続きます.
- \defは展開できないのでそのままです.
- \testを展開しようと試みますが,これは定義されていないのでエラーとなります.

従って結局「Undefined control sequence.」のエラーとなります.

\edef での展開を抑制した時には \noexpand を使います.\edef における置き換えテキスト内での \noexpand は後続のトークンの展開を抑制します.例えば
 \edef\testA{\def\noexpand\test{test}}
とすると,\test の展開が抑制されます.よって今度は「Undefined control sequence.」のエラーは出ず,
 \def\testA{\def\test{test}}
としたのと同等の結果を得ます.

一つのトークンではなく,いくつかのトークンの列の展開を抑制するにはトークンレジスタを使います.\edef における置き換えテキスト内に\the<トークンレジスタ>が現れた場合,トークンレジスタの中身に展開され,それ以上展開されません.例えば
 \def\testA{A}
 \def\testB{B}
 \toks0{\testB\testA}
 \edef\test{\testA\the\toks0}
とすると,\test は A\testB\testA に展開されます.
なお,e-TeX には \unexpanded というプリミティブがあります.これは上のようなトークンレジスタによる展開の抑制と同じ働きをします.上のコードは
 \edef\test{\testA\unexpanded{\testB\testA}}
と同じです.こちらの方が便利でしょう.

次のコードは,\arg の一回展開を \sample に渡すマクロ \test を作ります.
 \toks0\expandafter{\arg}
 \edef\test{\noexpand\sample{\the\toks0}}
\unexpanded は展開されていきますので,\expandafter で一端抑制することもできます.それを踏まえると、上のコードは次と等価です.
 \edef\test{\noexpand\sample{\expandafter\unexpanded\expandafter{\arg}}}

** トークンの制御 [#la5eed60]
*** \csname, \endcsname [#p4f470f6]
\csname ... \endcsnameは,その間に挟まれた文字列(を展開したもの)というコントロールシークエンスを実行します.たとえば
  \small

  \csname small\endcsname
は同等です.\csname と\endcsnameの間は展開されるので,
  \def\@tempa{small}
  \csname\@tempa\endcsname
としても\smallと等価になります.さらに,
  \csname \ifmmode csinmath\else csnotinmath\fi\endcsname
とすれば数式モードでは\csinmathに,非数式モードでは\csnotinmathと等価になります.

より正確に言えば,\csnameは展開可能なプリミティブで,一回展開により\endcsnameまでを読み取りその間(を展開した文字列)を名前に持つコントロールシークエンスに展開されます.従って,
  \expandafter\def\csname somecs\endcsname{SOMECS}

  \def\somecs{SOMECS}
と等価になります.

コントロールシークエンス名にはカテゴリーコードが11の文字しか使えませんが,\csname ... \endcsname内はその制限を受けません.たとえば
  \csname first_and_second\endcsname
は[first_and_second]という名前のコントロールシークエンスに展開されます.ただし,このようなコントロールシークエンスを定義する際には\csname/\endcsnameを使い
  \expandafter\def\csname first_and_second\endcsname{...}
として定義する必要があります.


* 基本練習問題 [#l9a8a164]
// いかがでしょうか。 学習効果が高い、しゃれた問題を作るのは大変そう。
// いかがでしょうか。 学習効果が高い,しゃれた問題を作るのは大変そう。
// 『TeXbook』を読めばいいってのは言いっこなし(^^;)
いい問題ができたら書き込みましょう。
// あと,“実際に処理させてみればわかる”という問題以外は“解答”も
// コメントとして入れておいてはどうでしょう.

// 以下の問題では,特に断らない限り,
// - 個々の文字のカテゴリーコードは plain TeX におけるデフォルトの値である
// - 個々の文字の \lccode/\uccode の値は plain TeX におけるデフォルトの値である
// 
//
// ものと仮定します.
// // 一応,上記の断り書きは入れておいたほうがよろしいのでは?

////// ごもっともです。
////// 入門者向けということで、デフォルトのカテゴリーコードになっていない可能性が
////// 入門者向けということで,デフォルトのカテゴリーコードになっていない可能性が
////// あるなどとはつゆほども思わない読者を想定していました。断り書きがなければ
////// 欠陥問題じゃないかと思うような読者にはぜひ執筆側に回ってもらいましょう(^^)

問題によっては解答がコメントとして書かれており,
上の「差分」から見ることができます。
問題によっては解答がコメントとして書かれており,上の「差分」から見ることができます。

** トークンの読み込み [#r9336262]
+あるユーザが LaTeX 文書のプリアンブルでマクロ \macro を下記のように定義した
(ただし,各行の先頭の行番号+コロンは解答の便宜のために付したもの).
このユーザは余分な空白を嫌って全ての行末に``%''を付加したのだが,
この定義中の各行末の % のうち,次の(1)~(3)の各々に該当するものはどれか.~
(1)その % がなければ,
\macro の使用時に行末に由来する空白が出力される可能性があるもの~
(2)その % があってもなくても \macro の挙動は変わらないもの~
(3)その % がなくても余分な空白は入らず,逆にその % があると
“行末をコメントアウト”というだけにとどまらない影響があるもの
+あるユーザが LaTeX 文書のプリアンブルでマクロ \macro を下記のように定義した(ただし,各行の先頭の行番号+コロンは解答の便宜のために付したもの).
このユーザは余分な空白を嫌って全ての行末に``%''を付加したのだが,この定義中の各行末の % のうち,次の(1)〜(3)の各々に該当するものはどれか.~
(1) その % がなければ,\macro の使用時に行末に由来する空白が出力される可能性があるもの~
(2) その % があってもなくても \macro の挙動は変わらないもの~
(3) その % がなくても余分な空白は入らず,逆にその % があると“行末をコメントアウト”というだけにとどまらない影響があるもの
  1: \def\macro{%
  2:     \ifnum\count0<0%
  3:         \setbox0=\hbox{%
  4:             \count0=-\count0%
  5:             \the\count0%
  6:         }%
  7:     \else%
  8:         \setbox0=\hbox{%
  9:             \the\count0%
 10:         }%
 11:     \fi%
 12:     \box0%
 13: }%
// (1) 1,3,6,8,10 行目の %
// (2) 2,5,7,9,11,13 行目の %
// (3) 4,12 行目の %
// 実際,“数値・寸法として読み取られる文字列”の直後の(多くとも 1 個の)
// 空白文字は“数値・寸法の終端”を表すものとして吸収される.
// また,コントロール・ワードを読み取る際にも,その直後の空白文字は
// 単にそのコントロール・ワードの終端を示すものとして無視される.
//
// そのため,2,4,5,7,9,11,12 行目の %((2),(3)に該当するもののうち,
// 13 行目のもの以外)は(1)には該当しないとわかる.
// 残りのもののうち,13 行目の % は \macro の定義が済んだ後にあり,
// \macro の挙動には関係しない(つまり(2)に該当).
// // なお,13 行目の % がなければ 13 行目の行末に由来する
// // 空白が入るが,このマクロ定義はプリアンブル(すなわち,垂直モードの箇所)で
// // 行われているため,この空白は何の影響ももたない.
// さらに残りのもの(つまり,1,3,6,8,10 行目の %)は,
// それらがなければ“{”,“}”の直後という吸収されない箇所に空白が入り,
// しかも,それは \macro の置換テキスト内に入るため \macro を用いた際に
// 出力される可能性がある.
// したがって,1,3,6,8,10 行目の % は(1)に該当する.
//
// さて,先に“2,4,5,7,9,11,12 行目の % は(1)には該当しない”ことをみたが,
// それらのうち,7,11 行目の % はコントロール・ワードを読み取った直後となり,
// (2)に該当する.
// 残る 2,4,5,9,12 行目の % は“数値として読み取られる文字列”の直後にあり,
// それらの % がないと“数値の終端”を探して後続のトークンを(必要があれば,
// それらの % があると“数値の終端”を探して後続のトークンを(必要があれば,
// マクロなどを展開しながら)調べ続ける.
// ただ,2,5,9 行目の場合,それらの次の行の先頭には
// \setbox(これは,展開されないプリミティブ)あるいは数字としては読めない
// トークン“}”があるため,2,5,9 行目の末尾の 0 はその直後に % が
// あったとしても数値 0 として確定する
// (したがって,2,5,9 行目の % は(2)に該当).
// 残る 4 行目と 12 行目の % については,個別に考えてみる.
//
// ・4 行目の % について:
// \count0=-\count0% の % によって \count0 の後の“数値の終端”を
// 欠いているため,代入の右辺の \count レジスタの番号は
// その直後にある \the\count0 を展開して得られる文字列を読まないと確定しない.
// そのため,\box0 の中身になるはずの \the\count0 の部分がその直前にある
// \count0=-\count0 の代入を行う前に展開されてしまう.
// 例えば,問題文にあるように \macro を定義した状態で“\count0=-1 [\macro]”を
// 処理してみると,“[-1]”という出力が得られる.
// 一方,4 行目のの % がない場合には,“\count0=-1 [\macro]”に対する出力は
// “[1]”となる.
// 実際,4 行目の末尾の(行末由来の)空白のところでその代入の右辺は確定するため,
// “\count0 の符号を反転させてから,\count0 の値を\the で文字列化”している.
// 結局,4行目の % があると“行末のコメントアウト”というだけでない影響があり,
// (3)に該当する.
//
// ・12 行目の % について:
// 定義の末尾の \box0% のところも,\box0 の直後に空白文字などの
// “数値の終端”を欠いているため,“\macro 1”のような記述を行うと
// \macro に続く数字列まで \box レジスタの番号として読み取ってしまい,
// (おそらく)意図通りではない出力が得られる.
// 一方,12 行目の % がない場合には,(4 行目の場合と同様に)出力する
// \box レジスタの番号は“0”と確定する.
// 結局,12 行目の % があると“行末のコメントアウト”というだけでない影響があり,
// (3)に該当する.
//
// [補足 1]
// 上述のとおり 13 行目の % はもともと \macro の挙動には関係しない.
// また,7,11 行目の % は,それがあろうとなかろうと \macro の
// 定義自体が変わらない.
// 残りの % については,それらの有無に応じて \macro の定義中の空白の
// 有無は変わってくるが,\macro の使用時の挙動を考えると上記のような結果となる.
//
// [補足 2]
// 今の例の \macro の定義の末尾に \def\macro{... \box0 } のごとく
// 明示的に空白文字を書き込むのを好まなければ,
// \def\macro{... \box\z@} のごとく 0 の別名を用いるのもよい
// (0 の代わりに \z@ を用いるのにはこのような積極的な意味がある場合も
// あることに注意).
//
// // 整理前の記述を保存
// +余分な空白を嫌って全ての行末に``%''が付加されているが、不要なものもある。どれか。
// +余分な空白を嫌って全ての行末に``%''が付加されているが,不要なものもある。どれか。
//  \def\macro{%
//      \ifnum\count0<0%
//          \setbox0=\hbox{%
//              \count0=-\count0%
//              \the\count0%
//          }%
//      \else%
//          \setbox0=\hbox{%
//              \the\count0%
//          }%
//      \fi%
//      \box0%
//  }%
// // ``0''の直後(五ヶ所)
// // (この例の定義中の 0 はいずれも“数値として”読み取られるので,
// // それに続く(多くとも 1 個の)空白文字は吸収される.)
// // コントロールワードの直後(``\else'', ``\fi'')
// // 最後の``}''の直後(このマクロの定義が水平モードで行われない場合)
// +前問の \macro の定義中の % のうち,単に不要というだけでなく
// “有害”であるものはどれか(前問では“あってもなくても構わない %”と
// “有害な %”の両方を尋ねているが,本問では特に“有害”なもののみを尋ねている).
// なお,本問においては“有害な %”とは
// >その % の有無によって単なる“空白トークンの有無”''以外''の相違が生じる可能性があるような %
// <のことを指す.
// // 保存部分終わり
/// “行末%”に関するはじめの問題を書いたものです。二ヶ所の有害な%については
/// 想定外でした。有害であることに気付いていなかったので問題文が不適切でしたが、
/// 想定外でした。有害であることに気付いていなかったので問題文が不適切でしたが,
/// 図らずも練習問題に含める失敗例としては面白い要素になっていたようですね。
/// 上手く発展させていただけたようで、ありがとうございます。
/// 上手く発展させていただけたようで,ありがとうございます。
/// いっそ二つの問題を統合してしまえればすっきりとしそうです。
// とりあえずまとめてみましたが,いかがでしょうか.

** カテゴリーコード [#gfea22ef]
+ “i”のカテゴリーコードが 0 で、“ ”(空白文字)のカテゴリーコードが 11 である場合、\macro This is a test. はどのようにトークン化されるか?
// \relax の代わりに [relax] と書いて,個々のコントロール・ワードを
// 明示することにすると,この問題の \macro This is a test. は
// [macro Th][s ][s a test].
// (最後のピリオドのみ,文字トークン)のように扱われる(ただし,問題文中で
// 断ってある i と空白文字以外の文字については,カテゴリーコードの変更は
// なされていないものと仮定).
+ ファイル latex.ltx における \strip@pt の定義を解析し,
このマクロの内部処理で用いられる \rem@pt の定義を単に
\def\rem@pt#1.#2pt{#1\ifnum#2>\z@ .#2\fi} としたのでは
うまくいかない理由を述べよ.
// \rem@pt では“\the + \dimen レジスタ”が与える文字列の末尾の“p_{12}t_{12}”
// を取り除くことになるので,通常の文字列“p_{11}t_{11}”を書式指定文字列に
// したのではパターンマッチが意図通りには行われない.
+ “i”のカテゴリーコードが 0 で,“ ”(空白文字)のカテゴリーコードが 11 である場合,\macro This is a test. はどのようにトークン化されるか?
+ ファイル latex.ltx における \strip@pt の定義を解析し,このマクロの内部処理で用いられる \rem@pt の定義を単に\def\rem@pt#1.#2pt{#1\ifnum#2>\z@ .#2\fi} としたのではうまくいかない理由を述べよ.
+ TeX Q & A 掲示板の [[17370:http://oku.edu.mie-u.ac.jp/~okumura/texfaq/qa/17370.html]] で提起された問題を解いてみよ.ヒント: latex.ltx における \@sanitize を利用するとよい.
// 続く議論を参照.

** 基本レジスタ [#o2f1fc77]
+ 整数型の数値の四則演算を行う方法を挙げよ.
実数型の数値の場合はどうか.
// 実数型の数値の乗除算以外については,\advance,\multiply,\divide という
// プリミティブを用いてできる(整数については \count レジスタを用い,
// 実数型の数値に対しては \dimen レジスタを用いる).
// 実数型の数値の乗算は,\dimen@=2.72\p@ \dimen@=3.14\dimen@
// (この時点で,\dimen@ の値は 2.72 * 3.14 pt となる)のように
// “係数”を使えばいい.
// 実数型の数値の除算は,整数の除算に帰着させる.
// \dimen0 = x [pt],\dimen2 = y (≠ 0) [pt] のとき,
// 単に \divide\dimen0 by \dimen2 とすると \dimen0 の値は x/y [sp]
// (しかも,小数点以下を切り捨てた値)となってしまうが,
// 何らかの形で 65536 x/y [sp] = x/y [pt] が得られればよい.
// 例えば,\multiply\dimen0 by 256 \divide\dimen2 by 256 としてから
// \divide\dimien0 by \dimen2 とすると \dimen0 の値は
// (256x)/(y/256) = 65536 x/y [sp] = x/y [pt] となる.
// (ただし,あくまで整数演算なので,分母は正確に y/256 になるとは限らず,
// その分の狂いが生じる.それを気にするような用途には,後述するような
// 正確な計算を用いることになる.)
// もちろん,『LaTeX 自由自在』で例示されているように,
// \count0 = \dimen0 のようにいったん \count レジスタに代入したのち,
// 整数の除算を用いて計算してもいい(もちろん,小数点以下の部分を
// 計算するには,“余りを 10 倍したのち除数で割る”操作を繰り返せばいい).
+ 以下の操作を行ったときの \skip0,\skip2 の最終的な値はどうなるか.
 \skip0=10pt plus 5pt minus 3pt
 \skip2=2\skip0
 \multiply\skip0 by 2
// 最終的には,\skip0 = 20pt plus 10pt minus 6pt,\skip2 = 20pt となる.
// “係数”をつけた場合には伸縮度が失われることに注意.
// 問: \skip レジスタの値を伸縮度も含めて実数倍するマクロを作成せよ.
+ \macroA,\macroB は引数をとらないマクロであるものとするとき,
 \edef\macro{\macroA\macroB}

 \toks@\expandafter{\macroA}
 \@temptokena\expandafter{\macroB}
 \edef\macro{\the\toks@\the\@temptokena}
はどのように違うか(ただし,\toks@,\@temptokena は LaTeX がすでに
用意している \toks レジスタ)?
また,後者の処理を \toks レジスタを用いずに実現するにはどうすればよいか.
// \toks レジスタを用いないほうでは,\macroA,\macroB に含まれるマクロなどは
// 展開され,条件処理も行われてしまうが,\toks レジスタを用いたほうでは
// \macroA,\macroB の置換テキストが単純に連結される.
// 例えば,\macroA,\macroB が
// \def\macroA{[\the\year]}
// \def\macroB{\ifnum\year>10000 ???\else OK\fi}
// のように定義されているとき,(この記述を行っている時点 2006 年では)
// \edef\macro{\macroA\macroB} は \def\macro{[2006]OK} と定義したのと
// 同じことになる一方,\toks レジスタを用いたほうは
// \def\macro{[\the\year]\ifnum\year>10000 ???\else OK\fi}
// と定義したのと同じことになる.
// [注] \the + \toks レジスタが与えるトークン列は \edef での置換テキスト
// 作成時には基本的にはそれ以上展開されないが,数値の読み取りなどの都合で
// 展開せざるを得ない場合には展開されてしまう.
// そのため,今の例でも \toks@ と \@temptokena の代わりに \toks0 と \toks2 を
// 用いた上で \edef\macro{\the\toks0\the\toks2} とはしていない.
// もっとも,\edef\macro{\the\toks0 \the\toks2} とすれば問題ない.
//
// また,\toks レジスタを用いたのと同じ,置換テキストの単純な連結は
// \expandafter\expandafter\expandafter\def
// \expandafter\expandafter\expandafter\macro
// \expandafter\expandafter\expandafter{\expandafter\macroA\macroB}
// という記述でも可能.
+ 次の記述を (La)TeX で処理すると,どのような出力が得られるか?
 \setbox0\hbox to10mm{X\hfil Y}
 \hbox to40mm{\copy0 \hfil \copy0}
 \hbox to40mm{\unhcopy0 \hfil \unhcopy0}
 \hbox to40mm{\box0 \hfil \box0}
 \setbox0\hbox to10mm{X\hfil Y}
 \hbox to40mm{\unhbox0 \hfil \unhbox0}
// 問: 不特定多数の整数や寸法を必要とする処理は,それらを文字列で
// 表したものを適当なマクロに保存すれば実現できる.
// では,不特定多数のボックスを必要とする処理を実現するには
// どうすればよいか.

** 定義と代入 [#gcea75b2]
+ \def\macro#1#2a#3.{#1;#2;#3;} と定義したとき、 \macro This is a test. の展開結果はどうなるか? \def\macro#1a#2#3.{#1;#2;#3;} だとしたらどうか?
+ あるユーザが,次のような記述を行った(\@firstoftwo,\@secondoftwo
については,必要があればファイル latex.ltx を参照のこと).
 \documentclass{article}
 \begin{document}
 \makeatletter
 \def\issubstring#1#2{%
    \def\@tempa##1#1##2\@nil{\def\@tempa{##2}}%
    \@tempa#2#1\@nil
    \ifx\@tempa\@empty \expandafter\@secondoftwo
    \else              \expandafter\@firstoftwo
    \fi}
 \makeatother
 \def\test#1#2{\issubstring{#1}{#2}%
    {``#1'' is contained in ``#2''.}%
    {``#1'' is not contained in ``#2''.}}
 \test{cat}{dog}
 \end{document}
// つまり,
// \issubstring は第 1 引数が第 2 引数の部分文字列であれば第 3 引数を実行し,
// そうでなければ第 4 引数を実行するようなマクロというつもりである.
実際,上記の \test{cat}{dog} の出力は意図通りのものであった.
問: \issubstring はどのようなマクロで,
\test{cat}{dog} の出力はどうなっていたのか?~
しかし,\test{aa}{a} を処理させるととんでもない結果が得られ,
このユーザは頭を抱えた.
// 実際,“aa”が“a”の部分文字列と判定されてしまったのだが,
問: いったいどのような結果が得られたのか?
また,\issubstring の定義のどこに問題があり,どう修正すべきであったか?
// \@tempa#2#1\@nil の行が問題.
// 実際,\issubstring の第 1 引数が ABA の形で,第 2 引数は AB の形である
// 場合(e.g. \issubstring{cat-cat}{cat-} などの場合)には,
// 第 2 引数と第 1 引数の先頭部分がつながって“意図しない位置に”\@tempa の
// 書式指定文字列が生じてしまう.
// ここでは,\@tempa#2\@empty#1\@nil のように \@empty を入れればよい.
// なお,\@empty も \issubstring の引数として用いられかねないような状況では,
// \@empty の代わりに %_{12} あるいは ^^@_{12} あたりを用いればよいだろう.
// [余談] LaTeX の内部処理用マクロ \in@ にもまったく同じ問題があるので,
// ユーザ自身が \in@ を用いる場合には注意が必要.
+ \def\macro#1#2a#3.{#1;#2;#3;} と定義したとき, \macro This is a test. の展開結果はどうなるか? \def\macro#1a#2#3.{#1;#2;#3;} だとしたらどうか?
+latex.ltx内で定義されているマクロ\@defaultunitsの使い方とその効果を述べ,定義を解析せよ.
// 文法上は \@defaultunits <たいていの代入操作><ごみ(存在しなくてもいい)>\@nnil
// という形式で用いることができるが,使用例は
//   \def\setparindent#1{\@defaultunits\parindent#1pt\relax\@nnil}
// のような具合に
//   \@defaultunits<寸法を代入できるもの><寸法または実数><単位>\relax\@nnil
// となっていることが大半(というより,そのような用法を念頭に置いていると
// 思われる).ここで,\relax は“代入に伴って,単位の後に続くマクロが
// 不用意に展開される”ことを防ぐために必要であることに注意.
// なお,今例示した \setparindent は引数として寸法または実数値
//(を 10 進表記した文字列)をとり,引数が寸法であるときには
// \parindent をその引数に設定し,数値であるときには単位 pt を補ってできる
// 寸法を \parident に代入するマクロ.\@defaultunits の効果(として
// 念頭に置いていると思われるもの)はこの例のように“必要に応じて
// デフォルトの単位を補うような”寸法の代入ができる,ということである.
// 問: \@defaultunits の文法上の書式の中で <たいていの代入操作> と
// 書いているように,\@defaultunits の直後では使えないような代入操作も
// 存在する.そのような操作の例を挙げよ(cf. “The TeXbook”の第 24 章に
// おける \afterassignment の説明).
+ 2 個のマクロ \macroA,\macroB の定義を入れ換える際に,
 \def\temp{\macroA}
 \def\macroA{\macroB}
 \def\macroB{\temp}
という記述と
 \let\temp\macroA
 \let\macroA\macroB
 \let\macroB\temp
という記述のどちらが意図通りに処理されるか?
また,意図通りに処理されないほうはどのような結果になるか.
// // \def と \let の相違を確認させる問題で,もっと気の利いた問題が
// // ありましたら,ぜひこの問題と差し替えてください(出題者より).
// 意図通りに処理されるのは後者.
// 前者では \macroA,\macroB のどちらを用いても無限ループに陥る(か,
// \macroA,\macroB を用いるまでに \temp が再定義されていたら
// “無関係なもの”が実行されてしまう).
// 実際,\temp が再定義されなかった場合について展開過程を
// 考えてみると,\macroA → \macroB → \temp → \macroA(以下,
// 繰り返しになる)のようになっている.
+LaTeX2eにはカウンタに親子関係を追加する\@addtoresetというマクロがある.では,この逆,「縁切り」のマクロ,つまり,<cntA>が子供<cntA1>,<cntA2>,・・・,<cntAn>をもっているときに,<cntAi>(i=1,2,...,n)を<cntA>の子供ではなくするマクロを実装せよ.
// amsdtx.cls で定義されているマクロ \@removefromreset は
// \@removefromreset{<child>}{<parent>}
// (<child>,<parent> はともに LaTeX のカウンタの名称)のように用いて,
// \cl@<parent> から \@elt{<child>} を取り除く
// という操作を行う(つまり,1 個のカウンタについて“縁切り”を行う).
// あとは,このマクロを \@for あたりのループ処理の中で使えばよい.
+ アルファベットからなる文字列の先頭の文字のみを大文字にして出力するマクロを以下の条件で作成せよ.
(1) アクセント記号はどこにもつかないことを前提とする
+ アルファベットからなる文字列の先頭の文字のみを大文字にして出力するマクロを以下の条件で作成せよ.~
(1) アクセント記号はどこにもつかないことを前提とする~
(2) 先頭の文字にアクセント記号がつくことも許容する
// 条件(1)の場合:
// \def\capitalize#1{\@capitalize #1\@empty}
// \def\@capitalize#1{%
//    \ifx#1\@empty\else
//       \ifnum`#1<`a
//          #1%
//       \else
//          \ifnum`#1>`z
//             #1%
//          \else
//             \ifcase`#1%
//                \or\or\or\or\or\or\or\or\or\or\or\or\or\or\or\or
//                \or\or\or\or\or\or\or\or\or\or\or\or\or\or\or\or
//                \or\or\or\or\or\or\or\or\or\or\or\or\or\or\or\or
//                \or\or\or\or\or\or\or\or\or\or\or\or\or\or\or\or
//                \or\or\or\or\or\or\or\or\or\or\or\or\or\or\or\or
//                \or\or\or\or\or\or\or\or\or\or\or\or\or\or\or\or\or
//                A\or B\or C\or D\or E\or F\or G\or H\or I\or J\or
//                K\or L\or M\or N\or O\or P\or Q\or R\or S\or T\or
//                U\or V\or W\or X\or Y\or Z%
//             \fi
//          \fi
//       \fi
//    \fi}
// なお,この定義の狙いは \edef\@tempa{\capitalize{alpha}} のようなことを
// してみるとわかるはず(こういう処理を考えないのなら,\uppercase あたりを
// 用いてもっと素直に定義すればいい).
//
// 条件(2)の場合:
// ここでは,アクセント記号は \"a のごとく“コマンドで”書くものと仮定.
// inputenc パッケージを併用して latin-1 エンコーディングあたりで
// 記述する場合や,Babel パッケージを使って "a のような記法を
// 有効にした場合については,別途考えて欲しい.
//
// 例のごとく『実践解説』2.1.3 項のサンプルコードと本質的には同じなので,
// そのサンプルと同様の(処理対象のテキストに \bgroup があっては
// いけないといった)制限がある.
// \newif\if@capitalize@firstletter
// \def\capitalize#1{%
//    \begingroup
//    \protected@edef\@tempa{#1}%
//    \begingroup
//    \def\@tempb##1##2{\def##1{##2}\@tempb}%
//    \expandafter\@tempb\@uclclist\@tempb\@empty
//    \def\i{I}\def\j{J}%
//    \global\@capitalize@firstlettertrue
//    \expandafter\@capitalize\@tempa\@nnil
//    \expandafter\endgroup\@tempa
//    \endgroup}
// \def\@capitalize{%
//    \let\@tempa\@empty
//    \@@capitalize}
// \def\@@capitalize{\futurelet\let@token\@@@capitalize}
// \def\@@@capitalize{%
//    \let\@tempb\@capitalize@checkchar
//    \ifx      \let@token\@nnil    \let\@tempb\@gobble
//    \else \ifx\let@token\@sptoken \let\@tempb\@capitalize@space
//    \else \ifx\let@token\bgroup   \let\@tempb\@capitalize@bgroup
//    \fi\fi\fi
//    \@tempb}
// \expandafter\def\expandafter\@list@of@special@char\expandafter{\@uclclist\i\j}
// \def\@capitalize@checkchar{%
//    \if@capitalize@firstletter \expandafter\@capitalize@checkchar@
//    \else                      \expandafter\@capitalize@skip
//    \fi}
// \def\@capitalize@checkchar@#1{%
//    \def\@tempb{#1}%
//    \def\@tempc{\@tfor\@tempc:=}%
//    \let\@tempd\@firstoftwo
//    \expandafter\@tempc\@list@of@special@char\do{%
//       \ifx\@tempb\@tempc
//          \global\@capitalize@firstletterfalse
//          \let\@tempd\@secondoftwo
//       \fi}%
//    \@tempd
//       \@capitalize@checkchar@@
//       {\expandafter\def\expandafter\@tempb\expandafter{#1}}%
//    \expandafter\expandafter\expandafter\def
//    \expandafter\expandafter\expandafter\@tempa
//    \expandafter\expandafter\expandafter{\expandafter\@tempa\@tempb}%
//    \@@capitalize}
// \def\@capitalize@checkchar@@{%
//    \let\@tempc\@tempb
//    \@onelevel@sanitize\@tempc
//    \edef\@tempd{\expandafter\@car\@tempc\@empty\@nil}%
//    \edef\@tempc{\expandafter\@cdr\@tempc\@empty\@nil}%
//    \ifx\@tempc\@empty
//       \edef\@tempd{\count@=`\@tempd\relax}\@tempd
//       \ifnum`A>\count@\else \ifnum`Z<\count@\else
//          \global\@capitalize@firstletterfalse
//       \fi\fi
//       \ifnum`a>\count@\else \ifnum`z<\count@\else
//          \global\@capitalize@firstletterfalse
//          \edef\@tempc{\uppercase{\def\noexpand\@tempb{\@tempb}}}%
//          \@tempc
//       \fi\fi
//    \fi}
// \def\@capitalize@skip{\@capitalize@skip@\@empty}
// \def\@capitalize@skip@#1\@nnil{%
//    \expandafter\expandafter\expandafter\def
//    \expandafter\expandafter\expandafter\@tempa
//    \expandafter\expandafter\expandafter{\expandafter\@tempa#1}}
// \begingroup
// \def\:{\def\@capitalize@space}%
// \expandafter\endgroup\: {%
//    \expandafter\expandafter\expandafter\def
//    \expandafter\expandafter\expandafter\@tempa
//    \expandafter\expandafter\expandafter{\expandafter\@tempa\space}%
//    \@@capitalize}
// \def\@capitalize@bgroup{%
//    \if@capitalize@firstletter \expandafter\@capitalize@bgroup@
//    \else                      \expandafter\@capitalize@skip
//    \fi}
// \def\@capitalize@bgroup@#1{%
//    \begingroup
//    \@capitalize#1\@nnil
//    \expandafter\endgroup
//    \expandafter\toks@\expandafter{\expandafter{\@tempa}}%
//    \@temptokena\expandafter{\@tempa}%
//    \edef\@tempa{\the\@temptokena\the\toks@}%
//    \@@capitalize}
//
// 問:“fake small caps”を出力するマクロ \fakesmallcaps を定義せよ.
// 例えば,文字サイズが \normalsize のところで用いられた
// \fakesmallcaps{\textsl{Fake Small Caps}} は
// \textsl{F{\small AKE} S{\small MALL} C{\small APS}} のような感じで
// 扱われて欲しい.
// ただし,\fakesmallcaps の引数には,(1) \text... の形の書体変更コマンド,
// (2)アクセント記号用のコマンド,(3) \l の類の特殊文字,の
// 3 種のコマンド以外のコマンドは含まれないと仮定してよい.
// // もちろん,まともに対処するには仮想フォントを利用するなり,
// // まともに small caps としてデザインされたフォントを一から作成するなり
// // することになるが,このようなマクロが役立つこともある.


**グルーピング [#i714208c]
+ 何らかの処理をグループ内でローカルに行う場合,
ときとして処理結果をグループの外に運び出したいことがある.
例えば,
 \begingroup
 <何らかの計算>
 \count@=...%%% 計算結果
 \endgroup
のようなことをして,しかも,“\endgroup の後においてもグループ内で設定した
\count@ の値を使いたい”という場合,どのようにすればよいか.
なお,\count@ は LaTeX 自身が提供するマクロなどのいたるところで用いられるので,
\count@ に対してグローバルな代入を行ってはいけないことに注意.
// 例えば,
// (1)   \expandafter\endgroup\expandafter\count@\expandafter=\the\count@\relax
// (2)   \edef\@tempa{\count@=\the\count@\relax} \expandafter\endgroup\@tempa
// (2')  \xdef\g@tempa{\count@=\the\count@\relax} \endgroup \g@tempa
// (2'') \xdef\g@tempa{\count@=\the\count@\relax} \aftergroup\g@tempa
// (3)   \global\somecnt\count@ \endgroup \count@=\somecnt
//     (ただし,\somecnt はあらかじめユーザ側で用意しておいた,
//     グローバル代入を行っても構わないような \count レジスタ)
// のような方法がある.
+あるユーザが(color パッケージを用いた上で)次のような記述を行ったところ,
\copy0 に対応する“青い strange”以降の“samples and”(ここは赤くするつもり)
あるいは“cases”(ここは水色にするつもり)までも青くなってしまった.
 {\color{red}%
 There
 \setbox0=\hbox{\color{blue}strange}%
 are \copy0\ samples
 and {\color{cyan}some more \copy0\ cases}.}
その理由および対処法を述べよ.
// “色”の処理は TeX の機能などではないことによる.
// つまり,色の設定・復元の処理は \special 経由で行わざるを得ず,
// その \special の設定のタイミングが TeX 自身のグルーピングの開始・終了とは
// 完全には一致していないことが原因.
// さらに具体的には,color パッケージ(に対する各種 def ファイルでの定義で)は
// “色の復元”をグループの終了と“概ね”連動させるために,
// 色の復元のための \special を \aftergroup を用いて配置する.
// // あくまで既存の def ファイルを調べた限りの話だが,本質的に異なる
// // 実装法は(処理系自身を色を取り扱えるように拡張しない限り)考えにくい.
// そのため,上記の例では,\color{blue} に対応する復元処理は
// strange の直後の閉じ括弧の直後(つまり,\box0 の *外*)に置かれてしまい,
// \copy0 の際には色に関しては“色の復元を伴わない青色への変更”だけが
// 行われてしまう,ということになっている.
// 対処法は,とりあえず
// \setbox0=\hbox{\textcolor{blue}{strange}}
// のごとく \textcolor を用いるとよい(\setbox0=\hbox{{\color{blue}...}}
// のように“color special のためのグルーピング”を追加してもよいが,
// これは \textcolor を用いるのとほとんど同じ).
// [余談] この問題の例を,\box0 の中身を \textcolor を用いて書き直した状態で
// 処理させたとしても,pdflatex(の,出題者の手元にある版
// (Version 3.141592-1.40.0-beta-20060213 (Web2C 7.5.5))では
// 意図通りの結果は得られない.これは,pdftex.def での色の復元処理は
// 明示的に“元の色であるはずの色に変更”するという処理であることによる
// (実際,\box0 の中身を代入したときの周囲の色と,2 回目の \copy0 の時点での
// ボックスの周囲の色とが異なっているために不都合が生じている).


** 条件分岐 [#eb863be6]
+あるユーザが
 \def\mymacro#1#2{% #1: 出力形式コード, #2: 文字列
    \leavevmode
    \ifcase#1\relax \textit{#2}%
    \or             \textbf{#2}%
    \or             \underline{#2}%
    \else           {#2}%
    \fi}
のようなマクロを作成して(これは,正常に動作する),
もう少しコードを削減しようと
 \def\mymacro#1#2{%
    \leavevmode
    \ifcase#1\relax \textit
    \or             \textbf
    \or             \underline
    \fi
    {#2}}
のように書き換えたら,とたんにエラーが生じるようになった.
その理由および対処法を述べよ.
// TeX の条件処理は,条件に合致する部分に対応する記述のみに
// 置換されるのでは *なく*,
//   必要な部分に到達するまで不要な部分を読み飛ばし,
//   そののち必要な部分の処理を実行して,さらに \fi までの不要な部分を
//   読み飛ばす
// という処理であることによる.
// 例えば,上記の \mymacro の最初の定義では,引数 #1 が 1 であるときは
// “1 番目の \or までを読み飛ばしたのち \textbf{#2} を処理し,そののち
// 2 番目の \or から \fi までを読み飛ばす”ため意図通りに処理される.
// 一方,2 番目の定義ではやはり引数 #1 が 1 であるときには,
// 1 番目の \or までを読み飛ばしたのち“\textbf を処理”しようとし,
// その際に \textbf の引数として \textbf の直後にある \or が用いられ,
// それはユーザの意図とは異なる処理である(実際,\textbf の内部で用いられる
// \ifmmode と \fi の間に \or が入り込み,エラーを引き起こす).
// 対処法は,この例のマクロに関しては
// \def\mymacro#1#2{%
//    \leavevmode
//    \ifcase#1\relax \expandafter\textit
//    \or             \expandafter\textbf
//    \or             \expandafter\underline
//    \fi
//    {#2}}
// のように \expandafter を用いて \textbf などの展開を行う前に
// 余分な \or ... \fi の読み飛ばしを行わせる,という方法がある.
// もっと一般的には,最初の定義のように条件分岐の個々の分岐先のみで
// 完結するように記述するか,
// \def\mymacro#1#2{%
//    \leavevmode
//    \let\mymacro@temp\empty
//    \ifcase#1\relax \let\mymacro@temp\textit
//    \or             \let\mymacro@temp\textbf
//    \or             \let\mymacro@temp\underline
//    \fi
//    \mymacro@temp{#2}}
// のような具合に“分岐先の処理を表すマクロ”を条件に応じて定義すればよい.
+ あるユーザが“ただの文字とコマンドを区別する”意図で
 \def\mymacro#1{% #1: 1 文字あるいは 1 コマンド
    \if\noexpand#1\relax <コマンドである場合の処理>
    \else                <文字である場合の処理>
    \fi}
という定義を行った.
問: \noexpand が必要である理由を述べよ.
また,文字とコマンドの判別を誤る場合について述べよ.
// \noexpand を用いずに \if#1\relax ... のようにしてしまうと,
// #1 の部分を展開してから比較が行われ意図通りの比較にならないので,
// \noexpand が必要.
// 実際,\def\macroA{aa},\def\macroB{XY} のように定義された \macroA,
// \macroB を考えると,\if\macroA\relax は \if aa\relax となり,
// \if による比較では 2 個の a が比較される(\macroA と \relax の
// 比較ではない).同様に,\if\macroB\relax では \if XY\relax となり,
// 比較されるのは X と Y である.
// また,\let\sb=_ で定義された \sb のような文字トークンのコピーに関しては,
// \if あるいは \ifcat での比較の際にはコピーされた文字の文字コードあるいは
// カテゴリーコードを持つものとして扱われる(実際,\if,\ifcat の比較では
// \sb と _ は区別されない).そのため,この問題の \mymacro では,
// 文字トークンのコピーに対しては文字であるか否かの判別を誤る.
+ 次に引用するコードは,ファイル amsgen.sty における \@ifempty の定義である
(\@firstoftwo,\@secondoftwo については,必要があればファイル latex.ltx
を参照のこと.なお,\@xp は \expandafter のコピーである).
 \long\def\@ifempty#1{\@xifempty#1@@..\@nil}
 \long\def\@xifempty#1#2@#3#4#5\@nil{%
   \ifx#3#4\@xp\@firstoftwo\else\@xp\@secondoftwo\fi}
このマクロの用法と,このマクロが誤動作する場合について述べよ.
// \@ifempty{<開き括弧と閉じ括弧の対応がとれたトークン列>}
//   {<そのトークン列が空文字列である場合の処理>}
//   {<そのトークン列が空文字列ではない場合の処理>}
// のように用いる.
// 実際,\@ifempty の引数 #1 に @_{11} が含まれない場合について考えると,
// #1 が空文字列でない場合には \@xifempty は
// \@xifempty <何かある>@@..\@nil という形で用いられ,
// <何かある> の部分が \@xifempty の引数 #1, #2 となり,
// #3 = @, #4 = . となって,\ifx#3#4 の比較結果は偽となる.
// 一方,\@ifempty の引数 #1 が空文字列である場合には,
// \@xifempty @@..\@nil を展開することになり,\@xifempty の各引数は
// #1 = @, #2 は空文字列, #3 = ., #4 = . で,\ifx#3#4 の比較結果は真となる.
// また,誤動作する場合については,\@ifempty の引数に @_{11} が含まれる
// 場合を調べればいい.実際,\@ifempty の引数 #1 が
// (1) <@_{11} を含まず,かつ,空でない文字列>@_{11}XX...
// (2) @_{11}@_{11}XX...
// (3) <@_{11} を含まない文字列><@_{11} の 2 個以上の繰り返し>
// (XX は同じ文字の繰り返し,... は任意の“開き括弧と閉じ括弧の対応が
// とれたトークン列”)といった場合に \@ifempty の引数 #1 が空文字列の
// 場合の処理が実行されてしまう.
// [余談] もっとも,@_{11} が紛れ込む場合,というのは TeX 文書中で
// “ユーザが原稿中に書き込んだ文字列”が空であるか否かを判定する際には
// 問題にならない.空文字列であるか否かの判定としてよく見かける
// \if/#1/ ...\else ...\fi のような処理に比べはるかに器用なので取り上げてみた.


**展開の制御 [#h72dcb23]
+ \def\A#1,#2{#2#1} \def\B#1;#2{#1,#2} \def\C{x;y} と定義されているとき、\A\B\C に\expandafter を適宜挿入して、展開結果が yx となるようにせよ。 
// \expandafter\expandafter\expandafter\A\expandafter\B\C
+ \def\macrocopy#1#2{\expandafter\let\csname #1\expandafter\endcsname\csname #2\endcsname}
のように定義された \macrocopy はどのようなマクロか?
この定義の中の 2 番目の \expandafter を忘れると,どのような不都合があるか?
// \macrocopy{macroA}{macroB} は \let\macroA\macroB という処理を行う,
// という具合に,\macrocopy はその第 1 引数から作成される control sequence を
// 第 2 引数から作成される control sequence のコピーにする.
// また,\macrocopy の定義中の 2 番目の \expandafter を忘れると,
// \macrocopy{<copy>}{<original>} は
// \expandafter\let\csname <copy>\endcsname\csname <original>\endcsname
// となるが,これは
// \let\<copy>\csname <original>\endcsname
// ということで,\<copy> を \csname のコピーにしたのち,<original> と
// \endcsname が取り残されてしまう(その結果,たいていの場合には余分な
// \endcsname があることによるエラーが生じる).
+ あるユーザが,“事物の名称とその事物の分類とを組にして登録するマクロ”と
“(登録済みの)事物の名称を与えると,
その事物と同じ分類先に属する(やはり,登録済みの)事物を与えるマクロ”を作成する,
という問題に出くわした.
例えば,“猫”・“犬”・“人間”の 3 項目のみが登録されていて
“猫”と“犬”の分類は“愛玩動物”で
“人間”の分類は“無用なもの”となっていたとすると,
互いに同じ分類に属する“猫”・“犬”の一方を与えたときには
“猫”・“犬”の両方が得られるが,
別の分類がなされている“人間”は出てこないようなマクロを作りたい,
というのである(もちろん,そのためには“登録用”のマクロも要る).
このユーザは“登録用”のマクロを次のように定義するところまでは自力でできた.
 \def\makeentry#1#2{% #1: 事物の名称,#2: 分類名
    \expandafter\gdef\csname @category@#1\endcsname{#2}%
    \expandafter\ifx\csname @entrylist@#2\endcsname\relax
       \expandafter\gdef\csname @entrylist@#2\endcsname{#1}%
    \else
       \expandafter\gdef
          \csname @entrylist@#2\expandafter\expandafter\expandafter\endcsname
          \expandafter\expandafter\expandafter{%
          \csname @entrylist@#2\endcsname
          ,#1}%
    \fi}
// もちろん,例えば次のように定義すると少しは読みやすいが,
// “故意に”上記のような定義を採用している.
// \def\makeentry#1#2{% #1: 事物の名称,#2: 分類名
//    \expandafter\gdef\csname @category@#1\endcsname{#2}%
//    \expandafter\ifx\csname @entrylist@#2\endcsname\relax
//       \expandafter\gdef\csname @entrylist@#2\endcsname{#1}%
//    \else
//       \expandafter\let\expandafter\@tempa\csname @entrylist@#2\endcsname
//       \expandafter\gdef\csname @entrylist@#2\expandafter\endcsname
//          \expandafter{\@tempa,#1}%
//    \fi}
// また,実際問題としては“重複登録”を回避する必要もあるが,
// “展開順序の変更”に関係しない点には必ずしもこだわらずに出題している.
問: \makeentry{<item>}{<category>}(<item>,<category> は文字列)のように
\makeentry を用いたときに定義される 2 個のマクロは
“項目名 <item> が与えられたときにその <item> が属する分類
(<category>)を与えるマクロ”と“分類名 <category> が与えられたときに,
その <category> に属する登録済み項目のコンマ区切りリストを与えるマクロ”
であることを確認し,それに基づいて“(登録済みの)事物の名称を与えると,
その事物と同じ分類先に属する(登録済みの)事物を与えるマクロ”を定義せよ.
// \makeentry{<item>}{<category>} は次の 2 個のマクロを定義する.
// ・\@category@<item>
//   これは <category> に展開されるので,
//   “<item> が属する分類を与えるマクロ”である.
// ・\@entrylist@<category>
//   これは,このマクロが未定義であるときには <item> に展開されるように定義され,
//   定義済みのときには“このマクロの置換テキストの後に ,<item> を追加したもの”
//   に展開されるように定義されるので,結局 \@entrylist@<category> は
//   “<category> に属する項目のコンマ区切りリスト”を与えるマクロである.
// また,与えた事物と同じ分類に属する項目を与えるマクロは,例えば,
// 次のように定義できる.
// \def\showsiblings#1{% #1: 事物の名称
//    \expandafter\ifx\csname @category@#1\endcsname\relax\else
//       \csname @entrylist@\csname @category@#1\endcsname\endcsname
//    \fi}
// // [余談] \csname @<array>@<index>\endcsname を <array>[<index>] と
// // 書き換えてみると,上記のコードの内側の
// // \csname @entrylist@\csname @category@#1\endcsname\endcsname
// // のところは entrylist[category[#1]] と書き換えられる
// // (こう書いてみると,どこかで見たような気がするのではないだろうか).
+ \edef あるいは \xdef によるマクロ定義において,
定義されるマクロの置換テキスト中に“定義時には展開したくない”
マクロ等が存在する場合には,そのマクロ等に \noexpand を前置して
 \edef\somecs{\noexpand\othercs{...}...}
という具合に展開を抑制すればよい,ということは“The TeXbook”をはじめとする
TeX のプリミティブを扱った解説書には(たいてい)書いてある.
しかし,今の例のように単純に \noexpand を用いたのでは,
展開の抑制は 1 回限りとなる(今の例の \somecs を,別のマクロ定義時に
\edef\yetanothercs{\somecs...} のような具合に用いると,
\somecs の置換テキスト中の \othercs はもはや保護されずに展開されてしまう).
では,何らかのマクロを“必要があれば何度でも保護”できるようにするには,
どのようにすればよいか.
// LaTeX ユーザであれば,“経験的”に“保護したいコマンドに \protect を
// 前置する”というやり方を知っていると思われるが,実際,
// \protected@edef(およびその変種)の実行時には
// \let\protect\@unexpandable@protect としてからマクロ定義を行い,
// そののち \protect の定義を必要があれば復元している.
// その \@unexpandable@protect の定義は
// \def\@unexpandable@protect{\noexpand\protect\noexpand}
// となっているため,\protect = \@unexpandable@protect の状態では
// \protect\somecs を展開しても再び \protect\somecs になり,
// \somecs を保護するだけでなく保護に用いる \protect 自身も保存される.
// そのため,\protect で保護したコマンドは必要があれば何度でも保護される
// (その代わり単純に \edef/\xdef を用いるのではなく \protected@edef 等を
// 用いることになるが,単純に \edef 等を用いたとしても“\protect の定義の
// 管理”をユーザ自身で行えば問題ない).
+ \def\A#1,#2{#2#1} \def\B#1;#2{#1,#2} \def\C{x;y} と定義されているとき,\A\B\C に\expandafter を適宜挿入して,展開結果が yx となるようにせよ。


**デバッグ [#me44b82b]
+ あるユーザが,一時的に文字列の幅を測定してその結果を用いるつもりで
 \def\mymacro#1{%
   \newdimen\tempwidth
   \settowidth\tempwidth{#1}%
   ...}
のような定義を行ったところ,別のユーザから“本当にそう定義していいかい?
そのマクロを 256 回以上使ってみるとどうなる?”とツッコミが入った.
上記の定義の問題点および対処法を述べよ.
// 問題点: 一時使用用のレジスタを \mymacro を用いるたびに新規割り当て
// しているため,いずれレジスタを使い果たしてしまう(eTeX ベースの
// システムではこの問題はあまり顕在化しないとは思うが,問題であることには
// 変わりがない).つまり,“メモリリーク”が存在する.
// 解決法: 一時使用用のレジスタはマクロの置換テキストの外部で割り当てればいい.
// e.g.
// \newdimen\tempwidth
// \def\mymacro#1{\settowidth\tempwidth{#1}...}
// なお,“ローカルに使う変数”が要る場合には,レジスタをローカルに
// 割り当てようとするのではなく(実際,\newdimen などのレジスタ
// 割り当て用マクロではグローバルにしか割り当てない),
// “レジスタの値のスコープ”をグルーピングで制御すればよい.

** 組版上の問題に由来する処理 [#o0e908b4]
+次のように書いたときに「あ」だけの行ができるのはなぜか?&br;
また,どうすれば「あれ,なんで?」と一行にできるか?&br;
+次のように書いたときに「あ」だけの行ができるのはなぜか? また,どうすれば「あれ,なんで?」と一行にできるか?
 \par
 \hbox{あ}
 れ,なんで?
// \par によって垂直モードに移行し,次の \hbox{あ} はそのまま垂直モードで
// 処理されていることによる.ここでは,\leavevmode を \hbox{あ} の
// 直前に置いて明示的に水平モードに移行すれば,“あ”のみの行ができることは
// 回避される(もっとも,“\hbox{あ}れ,…”ではなく単に“あれ,…”
// としてもこの問題の文字列に関しては解決するが,これは出題意図から
// 外れているだろう).
// 確かに意図とは違いますが,正当な理解に基づいての\hboxを外すという解は
// 正解ですね.ですので最初に「なぜか」という問いかけがあります
+あるユーザが今何ページであるかを本文中に書くために\thepageを記述した.ところが,正しくノンブルを拾えているところと,そうではないところが発生してしまった.これはなぜか(正しく拾えているところとそうではないところに何らかの傾向があるはずである).
// TeX の組版処理が“段落指向”であることによる.
// 例えば,ある段落が複数のページにまたがっている場合,
// その段落の中のページ分割位置以降の部分に \thepage が書かれていると,
// その \thepage に対応する出力は段落の開始位置を含むページ(状況によっては
// それ以前のページとなることもありうる)のページ番号となってしまう.
// 実際,“段落の組版処理を済ませて個々の行を作成してから”
// ページ分割位置が割り出されるため,段落の組版処理(その際に,段落全体が
// 文字列レベルでは確定する)の際にはページ分割に伴う \thepage の更新など
// 行わないで処理を済ませてしまう.
+ ページごとに脚注をリセットさせるという流儀がある.しかも,脚注が一つしかない場合は脚注のマーク(例えば,\dagger)のみで,複数ある場合は,脚注のマークに番号をつける(例えば,\dagger1,\dagger2,・・・)としたい.どうすればよいか?
// とりあえず,次のようなところ(本質的には『基礎解説』3.3 節の
// サンプルコードと同じ).
// ただし,\pagenumbering などの使用に伴い“(文字列として)同じページ番号を
// もったページ”が複数回現れることがあると,それらを区別できない場合がある
// (出力ルーチンにも細工を加えて,\thepage とは独立に数えた各ページの
// 通し番号を用いて個々のページを区別すれば,この問題は回避できる).
// \newcount\@fn@id
// \gdef\@top@fn@id{1}
// \gdef\@bottom@fn@id{2147483647}
// \def\@init@fn@idlist{%
//    \global\let\@fn@idlist\@empty
//    \gdef\@first@fn@id{1}
//    \gdef\@prev@fn@id{2147483647}%
//    \gdef\@prevpage@with@fn{}}
// \@init@fn@idlist
// \def\thefootnote{\textdagger\maybefnno}
// \gdef\maybefnno{\arabic{footnote}}
// \def\footnote{%
//    \@ifnextchar[%
//       \@xfootnote
//      {\expandafter\ifx\csname c@\@mpfn\endcsname\c@footnote
//          \@check@fn@id
//       \fi
//       \stepcounter\@mpfn
//       \protected@xdef\@thefnmark{\thempfn}%
//       \@footnotemark\@footnotetext}}
// \def\footnotemark{%
//    \@ifnextchar[%
//       \@xfootnotemark
//      {\@check@fn@id
//       \stepcounter{footnote}%
//       \protected@xdef\@thefnmark{\thefootnote}%
//       \@footnotemark}}
// \def\@check@fn@id{%
//    \global\advance\@fn@id\@ne
//    \ifnum\@bottom@fn@id<\@fn@id
//       \setcounter{footnote}\z@
//       \@get@next@fn@id
//    \fi
//    \protected@write\@auxout{}{\string\@footnote@id{\the\@fn@id}{\thepage}}}
// \def\@get@next@fn@id{%
//    \ifx\@fn@idlist\@empty
//       \gdef\@top@fn@id{1}%
//       \gdef\@bottom@fn@id{2147483647}%
//    \else
//       \expandafter\@get@next@fn@id@\@fn@idlist\@nil
//    \fi
//    \count@\@bottom@fn@id\relax
//    \advance\count@-\@top@fn@id\relax
//    \ifnum\count@>\z@
//       \gdef\maybefnno{\arabic{footnote}}%
//    \else
//       \global\let\maybefnno\@empty
//    \fi}
// \def\@get@next@fn@id@\@elt#1#2\@nil{%
//    \xdef\@top@fn@id{\@firstoftwo#1}%
//    \xdef\@bottom@fn@id{\@secondoftwo#1}%
//    \gdef\@fn@idlist{#2}}
// \def\@footnote@id#1#2{%
//    \def\@tempa{#2}%
//    \ifx\@prevpage@with@fn\@tempa\else
//       \ifx\@prevpage@with@fn\@empty\else
//          \@cons\@fn@idlist{{{\@first@fn@id}{\@prev@fn@id}}}%
//          \gdef\@first@fn@id{#1}%
//       \fi
//    \fi
//    \gdef\@prev@fn@id{#1}%
//    \gdef\@prevpage@with@fn{#2}}
// \AtEndDocument{%
//    \if@filesw
//       \clearpage
//       \immediate\write\@auxout{\string\@save@fn@idlist}%
//    \fi
//    \@init@fn@idlist
//    \let\@save@fn@idlist\@save@fn@idlist@}
// \def\@save@fn@idlist{%
//    \@cons\@fn@idlist{{{\@first@fn@id}{\@prev@fn@id}}}%
//    \global\let\@saved@fn@idlist\@fn@idlist
//    \@get@next@fn@id}
// \def\@save@fn@idlist@{%
//    \@cons\@fn@idlist{{{\@first@fn@id}{\@prev@fn@id}}}%
//    \ifx\@saved@fn@idlist\@fn@idlist\else \@tempswatrue \fi}

** フォントの取り扱い [#c4be128c]
+LaTeX2eではフォントの絶対的なサイズは指定できるが,相対的なサイズを指定するマクロはデフォルトではない.そこで,
 \fontscale{<ratio>}
とすると「現在のフォントサイズの<ratio>倍」にサイズ変更し,また
 \addfontsize{<dimen>}
とすると「現在のフォントサイズに<dimen>を加えた」サイズに変更するという
マクロを作成してみよ.
// \DeclareRobustCommand*\fontscale[1]{%
//    \dimen@\f@size\p@
//    \dimen@#1\dimen@
//    \dimen@ii\f@baselineskip\relax
//    \dimen@ii#1\dimen@ii
//    \edef\f@baselineskip{\the\dimen@ii}%
//    \fontsize\dimen@\f@baselineskip\selectfont
//    \ignorespaces}
// \DeclareRobustCommand*\addfontsize[1]{%
//    \let\@tempa\f@size
//    \@defaultunits\dimen@#1pt\relax\@nnil
//    \advance\dimen@\f@size\p@
//    \edef\f@size{\strip@pt\dimen@}%
//    \dimen@ii\f@baselineskip\relax
//    \dimen@ii\f@size\dimen@ii%%% \dimen@ii = <original baselineskip> * <new size>
//    \dimen@\@tempa\p@%%% \dimen@ = <original size>
//    \advance\dimen@ii .005\dimen@
//    %%% 以下の除算については,『LaTeX 自由自在』を参照.
//    \@tempcnta\dimen@ii
//    \count@\@tempcnta
//    \@tempcntb\dimen@
//    \divide\@tempcnta\@tempcntb
//    \edef\f@baselineskip{\the\@tempcnta}%
//    \multiply\@tempcnta\@tempcntb
//    \advance\count@-\@tempcnta
//    \multiply\count@ 10\relax
//    \@tempcnta\count@
//    \divide\@tempcnta\@tempcntb
//    \edef\f@baselineskip{\f@baselineskip.\the\@tempcnta}%
//    \multiply\@tempcnta\@tempcntb
//    \advance\count@-\@tempcnta
//    \multiply\count@ 10\relax
//    \divide\count@\@tempcntb
//    \edef\f@baselineskip{\f@baselineskip\the\count@ pt}%
//    %%% \f@baselineskip = <original baselineskip> * <new size> / <original size>
//    \fontsize\f@size\f@baselineskip\selectfont
//    \ignorespaces}
// ただし,必要があればフォント定義あるいは NFSS の内部処理に手を加えて
// “サイズ代用”を抑制することになる.
// // 行送りについても,文字サイズと同じ比率で拡大・縮小するように変更.
+TeXでは欧文は自動的にハイフネーションされる.しかし,ハイフネーションしてもハイフンを表示させたくない(つまり和文のように「普通に」改行しているように見せたい)こともある(例えばURLの表記).どのようにすればこのようなことができるか?
とすると「現在のフォントサイズに<dimen>を加えた」サイズに変更するというマクロを作成してみよ.
+TeXでは欧文は自動的にハイフネーションされる.しかし,ハイフネーションしてもハイフンを表示させたくない(つまり和文のように「普通に」改行しているように見せたい)こともある(例えばURLの表記).
どのようにすればこのようなことができるか?
なお,TeXを内部で使っているASCIIのEWBを使ったと明示されている書籍で,このような処理を行っていると思われるものは存在する(例:Petzold「プログラミングWindows第五版).
// // “フォントの取り扱い”っぽく解いてみると……
// “実体のない文字”をもった適当なフォントを作成し(仮想フォントでよい),
// そのフォントの“実体のない文字”を \hyphenchar に指定すればよい.
// 例えば,ecrm1000 の文字コード 127 の文字(オリジナルでは,ハイフンのひとつ)
// のプロパティを
// (CHARACTER O 177
//    (CHARWD R 0.0)
//    (CHARHT R 0.0)
//    (MAP
//       (MOVERIGHT R 0.0)
//       )
//    )
// くらいに変更して幅・高さが 0 で実体をもたない文字に変更したフォントを
// myecrm10 という名称にしたとする(ほかの文字には ecrm1000 の文字をそのまま
// 使うような仮想フォントにする).
// このようなフォントを用いつつ,下記の例のように \hyphenchar を
// 切り替えればよい.
// \documentclass{article}
// \DeclareFontShape{T1}{cmr}{m}{n}{<-> myecrm10}{}
// \def\hideautohyphen{\hyphenchar\font=127\relax}
// %%% ↑127 は“実体のない文字”の文字コード
// \def\useautohyphen{\hyphenchar\font=45\relax}
// %%% ↑ 45 は通常のハイフンの文字コード
// \def\text{%
//    This is a~meaningless sample text. This is a~meaningless sample text.
//    This is a~meaningless sample text. This is a~meaningless sample text.
//    This is a~meaningless sample text.\par}
// \begin{document}
// \fontencoding{T1}\selectfont
// \text
// \hideautohyphen \text
// \useautohyphen  \text
// \end{document}
//
// もっと丁寧にやるなら,“45”のような値は決めうちにするのではなく,
// 適宜退避・復元するとよい.
// なお,フォントにこだわらなければ,適当なマクロを用いて
// “ハイフンなしの分割”を行う文字列の個々の文字の間に
// \hskip0pt あたりを挟み込むといった方法もなくはない
// (が,ハイフネーションパターンをまったく考慮せずに分割してしまう).


**相互参照 [#m146461f]
+LaTeX2eでは節番号などを\label/\refによって参照することができる.だが書籍によっては番号だけではなく,例えば章のタイトルも参照したいことがある.例えば
 \chapter{イントロダクション}\label{intro}
とすることによって,
 \ref{intro}
では通常の参照,そして
 \titleref{intro}
とすると,タイトル(ここでは「イントロダクション」という文字列)が出力されるようにしたいというようなことである.
このような機構は一般にはクラスファイルに依存するが,ここではjsbook.clsを前提として\chapterのみを対象として実装してみよ.
なお,実際は\section以下の階層に組み込むほうがクラスファイルに依存しない可能性は高いが,\@startsectionの実装そのものが比較的複雑なので,本質的ではない問題を避けるためにjsbook.clsの\chapterを前提とした.
// \chapter の必須引数のほうは(参照時には余計なものとなる)強制改行などが
// 含まれる可能性があるので,オプション引数のほうを参照するものとして処理.
// また,番号なしの \chapter については参照しないものとみなしたが,
// そちらも参照するには,(*) というコメントをつけた行を \@schapter の定義に
// 追加すればよい.
// なお,\@chapter の定義自体についても jsbook.cls のバージョンによって
// 変わってくる可能性はあるが,\@chapter に対する変更は (*) の行の
// 追加のみなので,個々のバージョンに追随させる(だけでなく,さらに
// \@sect/\@ssect の定義にも同様の細工を仕込む)のは容易だろう.
// \def\@chapter[#1]#2{%
//   \ifnum \c@secnumdepth >\m@ne
//     \if@mainmatter
//       \refstepcounter{chapter}%
//       \typeout{\@chapapp\thechapter\@chappos}%
//       \addcontentsline{toc}{chapter}%
//         {\protect\numberline{\@chapapp\thechapter\@chappos}#1}%
//     \else\addcontentsline{toc}{chapter}{#1}\fi
//   \else
//     \addcontentsline{toc}{chapter}{#1}%
//   \fi
//   \chaptermark{#1}%
//   \addtocontents{lof}{\protect\addvspace{10\p@}}%
//   \addtocontents{lot}{\protect\addvspace{10\p@}}%
//   \begingroup%%% (*)
//   \let\label\@gobble%%% ← \label が見出し文字列に混入した場合への対処 (*)
//                     %%% なお,見出し文字列は \@makechapterhead の中で
//                     %%% 組版されるので,ここでは \label を単に無視してよく,
//                     %%% “\label を回収して置き直す”必要はない.
//   \let\index\@gobble \let\glossary\@gobble%%% (*)
//                     %%% ついでに \index,\glossary も無視
//   \protected@edef\@currenttitle{#1}%%%     (*)
//   \expandafter\endgroup\expandafter\def%%% (*)
//      \expandafter\@currenttitle\expandafter{\@currenttitle}%%% (*)
//   \if@twocolumn
//     \@topnewpage[\@makechapterhead{#2}]%
//   \else
//     \@makechapterhead{#2}%
//     \@afterheading
//   \fi}
// \let\@currenttitle\@empty
// \def\label#1{\@bsphack
//    \protected@write\@auxout{}%
//       {\string\newlabel{#1}{{{\@currentlabel}{\@currenttitle}}{\thepage}}}%
//   \@esphack}
// \def\ref#1{%
//    \expandafter\@setref\csname r@#1\endcsname\@firstoffirstoftwo{#1}}
// \def\titleref#1{%
//    \expandafter\@setref\csname r@#1\endcsname\@secondoffirstoftwo{#1}}
// \long\def\@firstoffirstoftwo#1#2{\@firstoftwo#1\@empty\@empty}
// \long\def\@secondoffirstoftwo#1#2{\@secondoftwo#1\@empty\@empty}

-----
* コメント [#f7eca8fe]

- 「入門」の一項目にするのではなく,別途「マクロの作成・応用」のようなページにされた方が良いように思いますが,いかがでしょうか。 この内容は「入門」のレベルを逸脱しているように思いましたので -- トニイ 2006/06/16
- [北見 けん] まあ、もう少しコンテンツが充実したら構成を見直すということでよろしいかと思います。 まずプリミティブを把握しておけば LaTeX などのマクロは自分で読めるようになるという意味では、入門としてはプリミティブの範囲に収まるものとしてもよいような気もします。 -- 北見 けん 2006/06/16 10:43
- このページの構成自体についてもいろいろご意見があるようなので、コメント欄を追加してみました。ついでに勝手ながら過去のコメントを表に出してみました。-- 北見 けん 2006/06/23
- [北見 けん] まあ,もう少しコンテンツが充実したら構成を見直すということでよろしいかと思います。 まずプリミティブを把握しておけば LaTeX などのマクロは自分で読めるようになるという意味では,入門としてはプリミティブの範囲に収まるものとしてもよいような気もします。 -- 北見 けん 2006/06/16 10:43
- このページの構成自体についてもいろいろご意見があるようなので,コメント欄を追加してみました。ついでに勝手ながら過去のコメントを表に出してみました。-- 北見 けん 2006/06/23
- とりあえず「タネ」を充実させてからでどうでしょう.何問か書きましたが,一日も経たずに解答がついてますね. -- 本田 &new{2006-06-24 (土) 10:53:29};
- 私の存在自体がお気に召さない人間が存在するようですので,私が作成した部分については撤去します. -- しっぽ愛好家 &new{2007-09-06 (木) 21:20:44};
- うーん。とても残念です。-- 北見 けん 2007-10-18 (木) 22:10:00 ← 手動タイムスタンプです
- そうおっしゃられるといささか心苦しいのですが,私としては「初心者の味方」気取りの連中に勝手なマネをされても黙っているわけではないことを行動で示す必要がありましたので.私が書いたものがないことで何か不都合があれば,「初心者の味方」気取りの連中(例えば「自分ではロクに回答しないにもかかわらず回答者つぶしをやる」ような人間)に埋めさせるのがよろしいでしょう. -- しっぽ愛好家 &new{2007-11-10 (土) 17:32:52};
- カテゴリ表の7,8の記号欄が逆になってます。日本語の説明の方が正しいです。 -- 斎藤 &new{2010-10-16 (土) 16:38:21};
>2010-10-17 修正済み

- #を含むファイル名が読めるようになりました。たすかりました。\catcode35=12としてからincludegraphics。後で\catcode35=6に戻す -- 斎藤 &new{2010-10-16 (土) 21:56:25};

#comment