[Swift] 独自演算子の優先順位を設定する

# はじめに
独自演算子を定義する時には、**演算子の優先順位**についての問題が気になってきます。

例として、Rにあるような、符号を被除数に一致させる剰余演算子を作成しました。
```swift
infix operator %%
func %%(left: Int, right: Int) -> Int {
    ((left % right) + right) % right
}
```
（参考：[Swiftで負の数に対する%演算が正にならない件 - Qiita](https://qiita.com/AseiSugiyama/items/5ffed727c031290fed61)）

しかし、上記のコードでは問題があります。
単体での使用は問題ありませんが、他の演算子と併用するとコンパイルエラーが発生します。
```swift
let n = -7
print(n %% 5)       // 3
print(10 + n %% 5)  // error: adjacent operators are in unordered precedence groups 'AdditionPrecedence' and 'DefaultPrecedence'
```
`%`と同じように、`n %% 5 = 3`が先に計算されて`10 + 3 = 13`という計算を行うには、**優先順位に関する情報**を設定しておく必要があります。

# 既存のprecedencegroupを利用する
**既存の演算子と同じ優先順位を設定する**のは簡単です。
例えば、`%`の優先順位は MultiplicationPrecedence なので、以下のように書くだけです。
```diff_swift
-infix operator %%
+infix operator %%: MultiplicationPrecedence
 func %%(left: Int, right: Int) -> Int {
     ((left % right) + right) % right
 }
```
これで先ほどのエラーは解消され、思い通りの結果になりました。
```swift
let n = -7
print(n %% 5)       // 3
print(10 + n %% 5)  // 13
```
このMultiplicationPrecedenceというものは、protocolではなく**precedencegroup**と呼ばれるものです。

以下は、既存のprecedencegroupの一覧です。(優先順位の高い順)
- BitwiseShiftPrecedence
`<<` `>>` `&<<` `&>>`
- MultiplicationPrecedence
`*` `/` `%` `&` `&*`
- AdditionPrecedence
`+` `-` `|` `^` `&+` `&-`
- RangeFormationPrecedence
`..<` `...`
- CastingPrecedence
- `is` `as` `as?` `as!`
- NilCoalescingPrecedence
`??`
- ComparisonPrecedence
`<` `<=` `>` `>=` `==` `!=` `===` `!==` `~=` `.<` `.<=` `.>` `.>=` `.++` `.!=`
- LogicalConjunctionPrecedence
`&&` `.&`
- LogicalDisjunctionPrecedence
`||` `.|` `.^`
- DefaultPrecedence
何も設定しなかった場合の優先順位。
これより下の優先順位よりは高いが、何より低いかは未定義。
- TernaryPrecedence
三項演算子(`?:`)
- AssignmentPrecedence
代入演算子(`=` `+=` `-=` `*=` `/=` `%=` `<<=` ...)

# 独自のprecedencegroupを定義する
独自の優先順位では、以下の4つを設定することができます。必須項目はありません。
- **lowerThan** ... どの優先順位より低いか
- **higherThan** ... どの優先順位より高いか
- **associativity** ... `left` | `right` | `none`
- **assignment** ... `true` | `false`

いくつか例を示します。

## 例１
先述の`%%`にカスタムの優先順位を設定してみます。
```swift
precedencegroup CustomPrecedence {
    lowerThan: MultiplicationPrecedence
    higherThan: AdditionPrecedence
    associativity: left
}

infix operator %%: CustomPrecedence
func %%(left: Int, right: Int) -> Int {
    ((left % right) + right) % right + 1
}
```
これは、乗算よりも低く加算よりも高い優先度です。
**associativity**は、`left`(右結合), `right`(左結合), `none`(非結合) のいずれかを設定できます。
```swift
left:  a %% b %% c  ->  (a %% b) %% c
right: a %% b %% c  ->  a %% (b %% c)
none:  a %% b %% c  ->  コンパイルエラー (error: adjacent operators are in non-associative precedence group 'CustomPrecedence')
```

## 例２
次は、**assignment**を使った例を紹介します。
```swift
precedencegroup MyPrecedence {
    lowerThan: TernaryPrecedence
    higherThan: AssignmentPrecedence
    assignment: false
}

infix operator %%=: MyPrecedence
func %%=(left: inout Int, right: Int) {
    left = left %% right
}

struct Test {
    var value: Int
}
var test: Test? = Test(value: -10)

test?.value %%= 3  // error: cannot convert value of type 'Int?' to expected argument type 'Int'
```
assignmentでは、代入演算子を定義する際に**オプショナルチェーンで表現された変数に対して代入することを許すか**を設定することができます。
AssignmentPrecedenceでは、この設定は`true`になっています。

# 参考
https://zenn.dev/kyome/articles/48f551222b339c

https://docs.swift.org/swift-book/documentation/the-swift-programming-language/declarations/#Operator-Declaration

https://developer.apple.com/documentation/swift/operator-declarations