Swiftの演算子名に使える文字

要は[The Swift Programming Language (Swift 4): Lexical Structure](https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/doc/uid/TP40014097-CH30-ID418)に書いてあるUnicodeのリストの話です。書いてある通りです。

私はUnicodeに詳しくなく、数字で言われても結局なんの文字なのかわからないので、ここに実際に書き出して傾向をみてみます。

オレオレ演算子を定義して__可読性を下げたい人__はぜひ参考にしてください。

# そもそも演算子がどういう扱いなのか

SwiftではLexical Structure(字句構造/有効なトークンと見なされる文字列)として次の5種類がある。

* Whitespace and Comments
* Identifiers
* Keywords and Punctuation
* Literals
* Operators

特にidentifierとoperatorは使える文字の面でだいぶ住み分けがされており、普段我々が変数や関数の命名に使っている文字は演算子では使えないと思ってよい。

<img width="595" alt="Screen Shot 2017-10-12 at 17.40.49.png" src="https://qiita-image-store.s3.amazonaws.com/0/84589/92c7ba62-d9dd-7e2e-b4f3-db972523bd47.png">

identifier用の文字を使うと専用のエラー(identifier_when_expecting_operator)が出る。
https://github.com/apple/swift/blob/bf42def404abcc9239cf7856475da2c80b86cc70/include/swift/AST/DiagnosticsParse.def#L421

# 演算子の文法

演算子には

* operator
* dot-operator

の2種類がある。普段 `.` は型の呼び出しや連続する演算子の区切りに使われるが、dot-operatorと呼ばれるドット始まりの演算子なら2文字目以降でもドットを使うことができる。ドット始まりでなければ `.` を使うことはできない。

演算子に使うことのできる文字でも、operator-head(何文字目でも使えるもの)とoperator-character(2文字目以降でないと使えない文字)の2種類がある。operator-characterには他の文字の後に続けて使う補助的な文字が指定されていて、あくまでUnicode側の都合。のはず。

全体の傾向としては、

* 数字の類は演算子に使えないが、数学記号は使える。
* アルファベットやひらがなや漢字といったような文字も演算子に使えない。
* 基本的に使えるのはU+3030まで。それ以降はほぼ使えない。
  * 残念ながら絵文字の大半はU+1F000以降で無縁。

# operator-headとして使える文字

## Basic Latin(基本ラテン文字)

要するにASCII。使えるのは次の文字とされている:

`/­  =­  -­  +­  !­  *­  %­  <­  >­  &­  |­  ^­  ~­  ?­`

演算子として使って問題なさそうな文字があがっているように見える。先述の通り、通常のoperatorでは`.`を1文字目に使うことはできない。また、 `prefix operator &` や `postfix operator ?` は既にお役目があるので我々が定義することはできない。

## Latin-1 Supplement(ラテン1補助)

* U+00A1–U+00A7 `¡ ¢ £ ¤ ¥ ¦ §`
* U+00A9 or U+00AB `© «`
* U+00AC or U+00AE `¬ ®`
* U+00B0–U+00B1, U+00B6, U+00BB, U+00BF, U+00D7, or U+00F7 `° ±　¶　» ¿ × ÷`

いわゆるLatin-1 Supplementにある通貨記号は演算子に使うことができる。一方、Basic Latinにいるドル記号は演算子に使えない(恐らくimplicit named parameterで忙しいため)。また、Currency Symbols(U+20A0-U+20CF)の通貨記号も演算子には使えず、identifier用にされている。
知的財産権記号は複数あるが、使えるのは`©`と`®`だけ。

使えない子:

* U+00A8( `¨` ): トレマ記号
* U+00AA( `ª` ): 序数標識
* U+00AD: ソフトハイフン
* U+00AF( `¯` ): マクロン
* U+00B2-U+00B3( `² ³` ): 上付き2、3
* U+00B4( `´` ): アキュート・アクセント
* U+00B5( `µ` ): マイクロ
* U+00B7( `·` ): 中黒
* U+00B8( `¸` ): セディーユ
* U+00B9( `¹` ): 上付き1
* U+00BA( `º` ): 序数標識
* U+00BC-U+00BE( ` ¼ ½ ¾` ): 分数
* U+00C0-U+00D6: Letters
* U+00D8-U+00DE: Letters
* U+00DF-U+00F6: Letters
* U+00F8-U+00FF: Letters

アクセント記号や数字、文字が省かれている。これらはidentifierの文字として使うことができる。

U+00ADソフトハイフンはXcode上で表示されないくせにidentifierとして使うことができる。良い子は次のような嫌がらせをしてはいけない。

<img width="193" alt="Screen Shot 2017-10-12 at 18.07.10.png" src="https://qiita-image-store.s3.amazonaws.com/0/84589/a79430da-e5e1-6158-3c37-4d02d7eac963.png">

## U+0100〜U+1FFF

色々な言語の文字が並んでいるブロック。演算子に使うことはできない。
ほぼ全てidentifierの命名用。

## General Punctuation(一般句読点)

* U+2016–U+2017 or U+2020–U+2027 `‖ ‗ † ‡ • ‣ ․ ‥ … ‧`
* U+2030–U+203E `‰ ‱ ′ ″ ‴ ‵ ‶ ‷ ‸ ‹ › ※ ‼ ‽ ‾`
* U+2041–U+2053 `⁁ ⁂ ⁃ ⁄ ⁅ ⁆ ⁇ ⁈ ⁉ ⁊ ⁋ ⁌ ⁍ ⁎ ⁏ ⁐ ⁑ ⁒ ⁓`
* U+2055–U+205E `⁕ ⁖ ⁗ ⁘ ⁙ ⁚ ⁛ ⁜ ⁝ ⁞`

使えない子:

* U+2018-U+201F: 色々な言語のクォーテーション。identifierにすら使えない。
* U+2028-U+2029: セパレータ。これもidentifierにすら使えない。
* U+202A-U+202F: 双方向テキスト
* U+202F: ノーブレークスペース
* U+203F-U+2040(`‿ ⁀`): ダブルインバーテッドブリーブ
* U+2054(`⁔`): 同上
* U+2060: 単語結合子
* U+2061: 関数適用
* U+2062: 不可視の乗算記号
* U+2063: 不可視の区切り文字
* U+2064: 不可視の加算記号
* U+2065: ---
* U+2066-U+2069: 双方向テキスト
* U+206A-U+206F

文字列方向の制御や不可視のものが取り除かれている一方で、我らがこめじるし `※` が採用されている。

## U+2070〜U+218F

* U+2070-U+209F: Superscripts and Subscripts
* U+20A0-U+20CF: Currency Symbols
* U+2100-U+214F: Letterlike Symbols
* U+2150-U+218F: Number Forms

演算子には使えない。identifierでどうぞ。

U+20D0-U+20FFはCombining Diacritical Marks for Symbolsなので演算子1文字目には使えない。

## U+2190〜U+3030

この辺りはブロックと呼ばれるかたまり単位でゴッソリ指定されている。目で見て意味がわかるものが多いので、実用的なものを作るならこの辺から採用すればいいかもしれないし、やっぱりわからないからボツかもしれない。

* U+2190–U+23FF
  * U+2190-U+21FF: Arrows
  * U+2200-U+22FF: Mathematical Operators
  * U+2300-U+23FF: Miscellaneous Technical
* U+2500–U+2775、U+2794–U+2BFF
  * U+2500-U+257F: Box Drawing
  * U+2580-U+259F: Block Elements
  * U+25A0-U+25FF: Geometric Shapes
  * U+2600-U+26FF: Miscellaneous Symbols
  * U+2700-U+27BF: Dingbats
      * U+2776-U+2793は➊や➀や➊の数字。identifier用にまわされた。
* U+2E00–U+2E7F: Supplemental Punctuation
* U+3001–U+3003、U+3008–U+3020、U+3030
  * U+3000-U+303F: CJK Symbols and Punctuation
    * U+3001-U+3003: 句読点
    * ~~U+3004-U+3007~~: Swiftガイドでは使用可能となっているが実際はidentifier用の文字で使うことはできない。つまり誤記。
    * U+3008-U+3020: 括弧やプライムクォート

    * ~~U+3021-U+3029~~: 蘇州号碼という数字。これもidentifier用。
    * ~~U+302A-U+302F~~: 声点、声符

`〃`(U+3003)も`々`(U+3005)も似たような文字だと思うのだが扱いが違う…

<img width="131" alt="Screen Shot 2017-10-14 at 1.19.49.png" src="https://qiita-image-store.s3.amazonaws.com/0/84589/b66a539a-7241-3e3c-5e42-3b4396c3ece9.png">

U+3008-U+3020では括弧やプライムクォートに混じって `〓〒〜〠` が使用可能になっている。そのくせU+3004 `〄` は使えない。郵便もJISも日本の記号って意味ではあまり変わらないと思うんだけど…

使えない子:

* U+2400-U+24FF
* U+2C00-U+2DFF
* U+2E80-U+2FFF

この辺りはほぼidentifier用。U+2400-U+243F Control PicturesとU+2440-U+245F Optical Character Recognitionはidentifierでも使えない。

# operator-characterとして使える文字

* U+0300–U+036F: Combining Diacritical Marks
* U+1DC0–U+1DFF: Combining Diacritical Marks
* U+20D0–U+20FF: Combining Diacritical Marks for Symbols
* U+FE00–U+FE0F: Variation Selectors
* U+FE20–U+FE2F: Combining Half Marks
* U+E0100–U+E01EF: Variation Selectors Supplement

補助的な文字なので演算子名の先頭にはもちろん使えないし、identifierと兼用になる。U+FE0FとU+FE0Eについては次の項目で。

# 使える絵文字

演算子名として使える範囲はほぼU+3030までといっていいので、U+1F000以降に見られるような、一般的によく見る絵文字の大部分を使うことはできない。

http://unicode.org/Public/emoji/5.0/emoji-data.txt

それでもそのU+3030までにいくつか絵文字があり、そのほとんどを使うことができる。
また、U+FE0FやU+FE0Eも使えるので、異体字(絵文字スタイル/テキストスタイル)を区別して演算子を作ることができる。

<img width="152" alt="Screen Shot 2017-10-12 at 19.55.29.png" src="https://qiita-image-store.s3.amazonaws.com/0/84589/f38749ee-37de-974d-b537-5ad0c860404f.png">

https://unicode.org/Public/emoji/6.0/emoji-variation-sequences.txt

逆にU+3030までに含まれていながら使えないのは

`# 0123456789 ™ ℹ Ⓜ`

である。

なお、「絵文字かどうか」「Swiftで演算子名に使えるか」には関連はないらしい。わけわからん。

||Unicode的に絵文字かどうか|演算子名に使えるか|
|---|---|---|
|〠||使える|
|〒||使える|
|〄|||
|©|絵文字|使える|
|®|絵文字|使える|
|℗|||
|™|絵文字||
|℠|||


# まとめ

〠ゆうびんやさんだよ〜

```swift
prefix operator 〠
prefix func 〠(_ code: String) -> String {
    return "〒\(code)"
}

〠"000-0000"    // "〒000-0000"
```

きっとみんな演算子定義なんてしないだろうなと思ってこの記事を書いたけど、やはり実用性はない。何をする演算子なのかわからないし記号の入力の仕方がわからない。この記事を書くにあたっては番号でぐぐったりPlaygroundに `\u{0000}` って書いて出力したりしたのをコピペした。