[Swift] 予約語, 関数名, 演算子

# Swiftにおける予約語

[Swift言語の公式ドキュメント](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/) - [`Lexical Structure`](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/lexicalstructure) - [`Keywords and Punctuation`](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/lexicalstructure#Keywords-and-Punctuation) に、次のように定義されています。

<img width="500" alt="rev.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283293/fb8eb8a1-d5c8-6f4c-824c-50951c510b8c.png" />


この記事で取り上げたいことは、説明文の先頭です。Google翻訳すると次の内容です。
（`backtick`を`バッククォート`に翻訳）

> 次のキーワードは予約済みであり、上記の「識別子」で説明したようにバッククォートでエスケープしない限り、識別子として使用することはできません。inout、var、let 以外のキーワードは、バッククォートでエスケープしなくても、関数宣言または関数呼び出しでパラメーター名として使用できます。メンバーの名前がキーワードと同じ場合、そのメンバーへの参照をバッククォートでエスケープする必要はありません。ただし、メンバーの参照とキーワードの使用の間に曖昧さがある場合は除きます。たとえば、self、Type、Protocol は明示的なメンバー式で特別な意味を持つため、そのコンテキストではバッククォートでエスケープする必要があります。

# 予約語 を 識別子 して使える
    
制約はありますが、バッククォートすれば”予約語”を”識別子”して使えるようです。（バッククォートしなくても使える場面もある）

ここでいう”識別子”ですが、この文章の中で例えられているのが、”関数のパラメタ名”、（classやstructの）”メンバー名”。


# 関数名で使えるか

関数は大きく、グローバルに定義する関数と、classやstruct内に定義する関数があります。

### グローバル関数

バッククォートすれば予約語が使えます。

```swift:グローバル関数
func `repeat`(count: Int, block: @escaping (Int)->Void) {
    for n in 0 ..< count {
        block(n)
    }
}
`repeat`(count: 10, block: { print($0) })
```

バッククォートしないと、関数宣言で<font color=red>`Keyword 'repeat' cannot be used as an identifier here`</font>エラー、
関数呼び出しで<font color=red>`Value pack expansion must contain at least one pack reference`</font>エラーとなります。

_（QiitaのコードブロックがSwiftのバッククォートした識別子に対応していませんね）_


### classやstruct内の関数

関数宣言のバッククォートは必要ですが、関数呼び出し時のバッククォートは不要です。

```swift:classやstruct内の関数
extension String {
    func `repeat`(_ count: Int) { String(repeating: self, count: count) }
}
let s = "ABC".repeat(3)
```

関数宣言でバッククォートしないと、<font color=red>`Keyword 'repeat' cannot be used as an identifier here`</font>エラーとなります。


# 関数の引数名で使えるか

これは、最初の説明文で使えることは自明ですが、一応確認しておきます。
バッククォートは関数宣言の引数名では不要ですが、引数のパラメタとしては必要です。


```swift
extension Int {
    func string(repeat: String) -> String { String(repeating: `repeat`, count: self) }
}
let s = 3.string(repeat: "ABC")
```

引数のパラメタでバッククォートしないと、<font color=red>`Expected expression after 'repeat'`</font>エラーとなります。


<br><br>
次が一番の本題です。

# 演算子に使えるか

独自演算子の定義も、普通の関数定義と同じ文法ですから、演算子に予約語が使えるか検証します。

```swift
infix operator `in` : ComparisonPrecedence
func `in` <T: Collection> (lhs: T.Element, rhs: T) -> Bool where T.Element: Equatable { rhs.contains(lhs) }
```

比較演算する実体の`in`関数はエラーになりませんが、その前の`infix operator`でエラーが出ます。
<font color=red>`'in' is considered an identifier and must not appear within an operator name`</font>

エラーは、「識別子は演算子に使えない」という意味です。

そうでした、忘れていました。
Swiftは、演算子に使える文字が決まっていて、そこに 英数字 はなく、基本は 記号文字 と 一部のUnicode文字 だけでした。



# 演算子に使える文字

[Swift言語の公式ドキュメント](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/) - [`Lexical Structure`](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/lexicalstructure) - [`Operators`](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/lexicalstructure#Operators) に、次のように定義されています。

<img width="500" alt="exp.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283293/6b9dbdb4-74c4-03bd-dc16-936001b077cb.png" />

一言で簡単に説明すると、標準の演算子が使っている”記号文字”の組み合わせだけ と言うことです。
識別子 は一切使えません。残念です。
`is`や`in`が演算子で使えると、コードを書くのがすごく楽になる場面があるのに・・・

**以上**