Qiita で集合や添字の数式を書こうとしてブチギれるその前に

Qiita に期待してはならない。

我々自身が立ち上がらなければならないのだ。

```math
\def\middlemid{\;\middle|\;}
\def\set#1{\left\{{#1}\right\}}
\def\setin#1#2{\left\{{#1} \middlemid {#2}\right\}}
\def\sub#1#2{{#1}_{#2}}
```

## 僕はとうとうブチギレた

Qiita では Markdown のパーザと MathJax がそれぞれ走っているが, そのやり方に問題があるのか知らんがとにかくおかしなことが起こる。

たとえば, 集合を書こうとしたとする。 コードブロックを使用すれば特に問題は起こらない。

    ```math
    \{a, b, c\}
    ```

```math
\{a, b, c\}
```

しかし, インラインでは話が違う。

    集合の要素すべてを書き出すような表記を外延的記法といい, たとえば $\{a, b, c\}$ のようになります。

> 集合の要素すべてを書き出すような表記を外延的記法といい, たとえば $\{a, b, c\}$ のようになります。

入力したはずの波括弧が消えた。 これはおそらく文中のバックスラッシュで Markdown としてのエスケープが優先され, ただの波括弧と化した結果, TeX 的には波括弧という文字ではなくブロックを構成する波括弧とみなされたためだろう。

> $\varnothing$ は元を持ちませんが, $\{\varnothing\}$ は空集合という元を持ちます。 よって $\varnothing$ と $\{\varnothing\}$ はまったく違う集合です。

とか言われたら読者は宇宙猫になりかねない(右クリックから TeX のソースを見てもらえばなにが起こったのかわかりやすいだろう)。

これを回避するためにバックスラッシュを重ね, Markdown としてエスケープされたバックスラッシュとすることで TeX のパーザに至るまでそのバックスラッシュを生き延びさせてやらなければならない。

    集合の要素すべてを書き出すような表記を外延的記法といい, たとえば $\\{a, b, c\\}$ のようになります。

> 集合の要素すべてを書き出すような表記を外延的記法といい, たとえば $\\{a, b, c\\}$ のようになります。

同様の問題として添字, あるいは下付き文字の問題がある。 やはり Markdown の強調と文法がかぶっているため, とくに一文に複数回登場する場合におかしなことになってしまうのだ。

    ここで正規四分位範囲 $\mathrm{NIQR}$ について考える。 $\mathrm{NIQR} = \frac{\mathrm{IQR}}{\mathrm{IQR}_{\mathcal{N}(0, 1)}}$ であるから、これを $\mathrm{IQR}$ について解いた $\mathrm{IQR} = \mathrm{NIQR} \cdot \mathrm{IQR}_{\mathcal{N}(0, 1)}$ を先の方程式に代入する。

> ここで正規四分位範囲 $\mathrm{NIQR}$ について考える。 $\mathrm{NIQR} = \frac{\mathrm{IQR}}{\mathrm{IQR}_{\mathcal{N}(0, 1)}}$ であるから、これを $\mathrm{IQR}$ について解いた $\mathrm{IQR} = \mathrm{NIQR} \cdot \mathrm{IQR}_{\mathcal{N}(0, 1)}$ を先の方程式に代入する。

ひどいね。 回避するためにはやっぱりバックスラッシュを入れる。

    ここで正規四分位範囲 $\mathrm{NIQR}$ について考える。 $\mathrm{NIQR} = \frac{\mathrm{IQR}}{\mathrm{IQR}\_{\mathcal{N}(0, 1)}}$ であるから、これを $\mathrm{IQR}$ について解いた $\mathrm{IQR} = \mathrm{NIQR} \cdot \mathrm{IQR}\_{\mathcal{N}(0, 1)}$ を先の方程式に代入する。

> ここで正規四分位範囲 $\mathrm{NIQR}$ について考える。 $\mathrm{NIQR} = \frac{\mathrm{IQR}}{\mathrm{IQR}\_{\mathcal{N}(0, 1)}}$ であるから、これを $\mathrm{IQR}$ について解いた $\mathrm{IQR} = \mathrm{NIQR} \cdot \mathrm{IQR}\_{\mathcal{N}(0, 1)}$ を先の方程式に代入する。

回避できるならいいじゃん, と思うだろうか? しかし, おそらく大抵の人は Qiita の画面ではなくそれぞれのエディタで記事を書いて, Qiita に貼り付けているだろう。 だって Qiita のオンラインエディタってレンダリングがクソ重いんだもん! たとえば僕の場合は VSCode + Markdown Preview Enhanced (KaTeX) を使用している。 そうすると, 当然 Qiita 用の応急処置をクソ真面目に読んでくれちゃって意図した表示にならない, 下手するとエラーを起こす。

もちろん悪いのは Qiita なのだが(ドルで囲まれた部分は変換しないくらいの処理を噛ませられなかったのか??), だからといって Qiita に期待するのはどのように愚かな! 自分でなんとかするしかあるまい。

結論から言えば, Qiita でも私の執筆環境でもマクロの定義ができる。 ならば, 集合や添字など, 問題が出そうな記法はマクロを介して出力すればよい。

たとえば, 以下のようなマクロを記事の最初の方に仕込んでおく。

    ```math
    \def\middlemid{\;\middle|\;}
    \def\set#1{\left\{{#1}\right\}}
    \def\setin#1#2{\left\{{#1} \middlemid {#2}\right\}}
    \def\sub#1#2{{#1}_{#2}}
    ```

私の環境では KaTeX なので, `\def`がグローバルに効いてくれないので代わりに`\gdef`を使う。 Qiita に貼っつけたあと`g`は消す。 まあ, 上から下まで眺めてバックスラッシュを入れるのにくらべたら楽な作業だ。 どうしても嫌なら MathJax に戻そう。

そして, 集合を書きたかったら`\set`を使う。

    $\varnothing$ は元を持ちませんが, $\set{\varnothing}$ は空集合という元を持ちます。 よって $\varnothing$ と $\set{\varnothing}$ はまったく違う集合です。

> $\varnothing$ は元を持ちませんが, $\set{\varnothing}$ は空集合という元を持ちます。 よって $\varnothing$ と $\set{\varnothing}$ はまったく違う集合です。

いかがだろうか。 これなら Qiita にそのまま貼っても波括弧が勝手に消えることはない。 ついでなので`\left`と`\right`で囲んでおいた。 $\displaystyle \set{\frac{2}{3}}$ のように縦に長いのも朝飯前だ。 これは逆に便利になったのでは?

内包的記法用に`\setin`も作っておいた。 無論, `\set`のなかに`\mid`を入れてもいいのだが, 先程のように縦に長くなると`\mid`がでかくなってくれない。 `\middlemid`というのを作ったがそこまでやるなら専用にマクロを作ってもいいだろう。 [マクロツイーターさんのところで紹介されていた方法](https://zrbabbler.hatenablog.com/entry/20120411/1334151482)では, なぜか空白がでかくなりすぎるので(MathJax の仕様?)涙を飲んで関係演算子として扱うのを諦めざるを得なかったが。

    `\set`と`\mid`で分数を含むような集合の内包的記法をすると $\displaystyle \set{x \in \mathbb{R} \mid x > \frac{\pi}{2}}$ のようになってしまいますが, `\setin`では $\displaystyle \setin{x \in \mathbb{R}}{x > \frac{\pi}{2}}$ となり見栄えがよいです。

> `\set`と`\mid`で分数を含むような集合の内包的記法をすると $\displaystyle \set{x \in \mathbb{R} \mid x > \frac{\pi}{2}}$ のようになってしまいますが, `\setin`では $\displaystyle \setin{x \in \mathbb{R}}{x > \frac{\pi}{2}}$ となり見栄えがよいです。

添字の場合には`\sub`を使用する。

    総和記号の記法はプログラマにとってはある意味わかりやすいかもしれません。 たとえば, $\sub{\sum}{i = 0}^{n} \sub{a}{i}$ というのは, $i$ に $0$ から順に代入して, $\sub{a}{0}, \sub{a}{1}, \sub{a}{2}, \ldots, \sub{a}{n}$ とし, それらの合計を取ります。 つまりは, `for`文に相当します。 $\sub{\sum}{a \in S} a$ のようにして`for each`のような書き方をする場合もあります。

> 総和記号の記法はプログラマにとってはある意味わかりやすいかもしれません。 たとえば, $\sub{\sum}{i = 0}^{n} \sub{a}{i}$ というのは, $i$ に $0$ から順に代入して, $\sub{a}{0}, \sub{a}{1}, \sub{a}{2}, \ldots, \sub{a}{n}$ とし, それらの合計を取ります。 つまりは, `for`文に相当します。 $\sub{\sum}{a \in S} a$ のようにして`for each`のような書き方をする場合もあります。

こちらはだいぶタイプ数が増えてしまい不便ではある。 アンダースコアの問題は Qiita でも起こったり起こらなかったりでよくわからず, 精神衛生上よろしくないので, 保険としては仕方ないのではあるが。

## まとめ

Qiita 仕事しろ。