LaTeX において長さを数値で調整できる矢印

LaTeX で矢印の長さを調整する際に、`\rightarrow`、`\longrightarrow`、`\longlongrightarrow`…… というように long を付け足していくのではなく、数値で調整できると便利なので作りました。

![Screenshot 2017-05-07 17.19.40.png](https://qiita-image-store.s3.amazonaws.com/0/31593/1882429f-b470-1296-50eb-e081a1103fb0.png)

```latex:arrow.tex
\documentclass{article}

\usepackage{expl3}
\usepackage{graphicx}
\usepackage{amsmath}
\usepackage{amssymb}
\usepackage{newtxtext}
\usepackage{newtxmath}
\usepackage{silence}
\WarningsOff[latexfont]

\ExplSyntaxOn
\cs_new_eq:NN \Repeat \prg_replicate:nn
\cs_new_eq:NN \If \bool_if:nTF
\cs_new_eq:NN \Compare \int_compare_p:nNn
\ExplSyntaxOff

\newcommand{\mathstyle}[1]{\mathchoice{#1}{#1}{{\scriptsize #1}}{\tiny #1}}

\newcommand{\makearrowr}[3][0]{\mathrel{\Repeat{#1}{#2\joinrel}#3}}
\newcommand{\makearrowl}[3][0]{\mathrel{#2\Repeat{#1}{\joinrel#3}}}
\newcommand{\makearrowb}[4][0]{\mathrel{#2\joinrel\Repeat{#1}{#3\joinrel}#4}}
\newcommand{\makearrowx}[5][0]{\mathrel{\If{\Compare{#1}={0}}{#2}{#3\joinrel\Repeat{(#1) - 1}{#4\joinrel}#5}}}

\renewcommand{\to}[1][0]{\makearrowr[#1]{\relbar}{\rightarrow}}
\newcommand{\ot}[1][0]{\makearrowl[#1]{\leftarrow}{\relbar}}
\newcommand{\To}[1][0]{\makearrowr[#1]{\Relbar}{\Rightarrow}}
\newcommand{\oT}[1][0]{\makearrowl[#1]{\Leftarrow}{\Relbar}}

\newcommand{\tot}[1][0]{\makearrowx[#1]{\leftrightarrow}{\leftarrow}{\relbar}{\rightarrow}}
\newcommand{\ToT}[1][0]{\makearrowx[#1]{\Leftrightarrow}{\Leftarrow}{\Relbar}{\Rightarrow}}

% mapping
\newcommand{\mto}[1][0]{\makearrowx[#1]{\mapsto}{\vdash}{\relbar}{\rightarrow}}
\newcommand{\otm}[1][0]{\makearrowx[#1]{\mathstyle{\reflectbox{\(\mapsto\)}}}{\leftarrow}{\relbar}{\dashv}}
\newcommand{\Mto}[1][0]{\makearrowb[#1]{\mathrel{\mathstyle{\raisebox{0.23ex}{\scalebox{1}[0.6]{\(\mid\)}}\mkern-1mu}}}{\Relbar}{\Rightarrow}}
\newcommand{\otM}[1][0]{\makearrowb[#1]{\Leftarrow}{\Relbar}{\mkern-1mu\mathrel{\mathstyle{\raisebox{0.23ex}{\scalebox{1}[0.6]{\(\mid\)}}}}}}

% partial
\newcommand{\pto}[1][0]{\makearrowr[#1]{\relbar}{\rightharpoonup}}
\newcommand{\otp}[1][0]{\makearrowl[#1]{\leftharpoonup}{\relbar}}

% injective
\newcommand{\ito}[1][0]{\makearrowb[#1]{\lhook}{\relbar}{\rightarrow}}
\newcommand{\oti}[1][0]{\makearrowb[#1]{\leftarrow}{\relbar}{\rhook}}

% surjective
\newcommand{\sto}[1][0]{\makearrowr[#1]{\relbar}{\rightarrow\kern-1.8ex\rightarrow}}
\newcommand{\ots}[1][0]{\makearrowl[#1]{\leftarrow\kern-1.8ex\leftarrow}{\relbar}}

\begin{document}

\[a \to[0] b \to[1] c \to[2] d \to[3] e \to[4] f\]
\[a \ot[0] b \ot[1] c \ot[2] d \ot[3] e \ot[4] f\]
\[a \To[0] b \To[1] c \To[2] d \To[3] e \To[4] f\]
\[a \oT[0] b \oT[1] c \oT[2] d \oT[3] e \oT[4] f\]
\[a \tot[0] b \tot[1] c \tot[2] d \tot[3] e \tot[4] f\]
\[a \ToT[0] b \ToT[1] c \ToT[2] d \ToT[3] e \ToT[4] f\]
\[a \mto[0] b \mto[1] c \mto[2] d \mto[3] e \mto[4] f\]
\[a \otm[0] b \otm[1] c \otm[2] d \otm[3] e \otm[4] f\]
\[a \Mto[0] b \Mto[1] c \Mto[2] d \Mto[3] e \Mto[4] f\]
\[a \otM[0] b \otM[1] c \otM[2] d \otM[3] e \otM[4] f\]
\[a \pto[0] b \pto[1] c \pto[2] d \pto[3] e \pto[4] f\]
\[a \otp[0] b \otp[1] c \otp[2] d \otp[3] e \otp[4] f\]
\[a \ito[0] b \ito[1] c \ito[2] d \ito[3] e \ito[4] f\]
\[a \oti[0] b \oti[1] c \oti[2] d \oti[3] e \oti[4] f\]
\[a \sto[0] b \sto[1] c \sto[2] d \sto[3] e \sto[4] f\]
\[a \ots[0] b \ots[1] c \ots[2] d \ots[3] e \ots[4] f\]
\[x \to[((1 + 2) * 3 - 4) / 5 + 6] y\]
\[x \to[7] y\]

\end{document}
```

基本的には expl3 パッケージを利用して `\Repeat` マクロを定義して繰り返しをおこなっているだけです。`\Repeat` の引数に数式をそのまま入れられるのがちょっとしたポイントです。

なお、長さの調整は棒（`\relbar` か `\Relbar`）を継ぎ接ぎする方法を取っています。なお、`\joinrel` は二項関係の記号どうしの間のスペースを良い感じに詰めてくれるマクロです。

実装の詳細についてですが、`\Mto` / `\otM` の実装は見た目を美しくするために若干複雑になっています（`\mid` をそのまま使っても良かったのですが、ちょっと大きすぎるなと思ったので……）。また、`\sto` / `\ots` の実装には素直に `\twoheadrightarrow` / `\twoheadleftarrow` を使えば良いと思うかもしれませんが、これらの矢印はなぜか線が細く `\relbar` とうまく結合しないので、矢印を重ね打ちしました。

expl3 についての文献はまだあまり充実していませんが、LaTeX におけるプログラミングを圧倒的に楽にしてくれると思いました。