Swift演算子まとめ

Swiftの演算子、まとめました。

【2018/09/05追記】
内容はSwift2のものであり、(筆者がiOS開発を離れているため)更新の予定もありません😉
編集リクエストは大歓迎です。@BlueRayi さんありがとうございました。

# 演算子一覧
Prefix演算子

|    演算子   |     作用     |
|:----------:|:-----------:|
| ++         | 1加算※      |
| --         | 1減算※      |
| !          | 論理NOT      |
| ~          | ビットNOT     |
| + (単項)    | +符号        |
| - (単項)    | -符号        |

Postfix演算子

|    演算子   |     説明     |
|:----------:|:-----------:|
| ++         | 1加算※      |
| --         | 1減算※      |

Infix演算子

|     演算子     |   説明           | 結合律 | 優先順位 |
|:-------------:|:---------------:|:-----:|:-------:|
| <<            | 左ビットシフト     | 無結合 | 160    |
| >>            | 右ビットシフト     | 無結合 | 160    |
| *             | 乗算             | 左結合 | 160    |
| /             | 除算             | 左結合 | 160    |
| %             | 剰余             | 左結合 | 160    |
| &*            | オーバーフロー乗算  | 左結合 | 160    |
| &             | ビットAND         | 左結合 | 160    |
| +             | 加算             | 左結合 | 140    |
| -             | 減算             | 左結合 | 140    |
| &+            | オーバーフロー加算  | 左結合 | 140    |
| &-            | オーバーフロー減算  | 左結合 | 140    |
| &#124;        | ビットOR          | 左結合 | 140    |
| ^             | ビットXOR         | 左結合 | 140    |
| ..<           | 半開区間          | 無結合 | 135    |
| ...           | 閉区間            | 無結合 | 135    |
| is            | 型チェック         | 左結合 | 132    |
| as as? as!    | 型キャスト         | 左結合 | 132    |
| ??            | Nil Coalescing   | 右結合 | 131    |
| <             | 未満              | 無結合 | 130    |
| <=            | 以下              | 無結合 | 130    |
| >             | より上            | 無結合 | 130    |
| >=            | 以上              | 無結合 | 130    |
| ==            | イコール           | 無結合 | 130    |
| !=            | ノットイコール      | 無結合 | 130    |
| ===           | 同じオブジェクト    | 無結合 | 130    |
| !==           | 違うオブジェクト    | 無結合 | 130    |
| ~=            | パターンマッチ      | 無結合 | 130    |
| &&            | 論理AND           | 左結合 | 120    |
| &#124;&#124;  | 論理OR            | 左結合 | 110    |
| ?:            | 三項条件           | 右結合 | 100    |
| =             | 代入              | 右結合 | 90     |
| *=            | 乗算と代入         | 右結合 | 90     |
| /=            | 徐算と代入         | 右結合 | 90     |
| %=            | 剰余と代入         | 右結合 | 90     |
| +=            | 加算と代入         | 右結合 | 90     |
| -=            | 減算と代入         | 右結合 | 90     |
| <<=           | 左ビットシフトと代入 | 右結合 | 90     |
| >>=           | 右ビットシフトと代入 | 右結合 | 90     |
| &=            | ビットANDと代入    | 右結合 | 90     |
| &#124;=       | ビットORと代入     | 右結合 | 90     |
| ^=            | ビットNOTと代入    | 右結合 | 90     |
| &&=           | 論理ANDと代入      | 右結合 | 90     |
| &#124;&#124;= | 論理ORと代入       | 右結合 | 90     |

※…++演算子、--演算子はSwift3.0で削除された。

# 用語

**単項演算子(Unary)**
被演算子(Operand)が1つの演算子。
前置のもの(prefix)と後置のもの(postfix)がある。

**二項演算子(Binary)**
被演算子が2つの演算子。
被演算子の間に置かれる(infix)。

**三項演算子(Ternary)**
被演算子が3つの演算子。
?:の一つだけ(infix)。

**優先順位**
数値が大きいものほど先に演算される。
単項演算子は二項演算子よりも優先順位が高い。

**結合律**
優先順位が同じ演算子が並んだ場合は、左結合のものは左から、右結合のものは右から演算される。
(同じ優先順位で、左結合のものと右結合のものは混在しない。)
無結合の演算子が並んだ場合はエラーとなる。

```swift
let result = 2 + 3 + 4  // 左から

var str1: String?
var str2: String?
let string = str1 ?? str2 ?? "string" // 右から

let int1 = 1
let int2 = 2
let int3 = 3
int1 == int2 == int3 // エラー
```

# 各演算子

## 代入演算子(Assignment Operator)
### =
値の代入。
タプルの場合はそれぞれに代入。
Objective-Cと異なり、値を返さない。

```swift
let (x, y) = (1, 2)
// x = 1, y = 2

if x = y { // 判定する値が返らない
    // エラー
}
```

## 算術演算子
### +, -, *, /
Objective-Cと異なり、オーバーフローを許容しない。

```swift
var i: Int8 = 127 // Int8の最大数
i++  // エラー
```

### %
a % b は

```
a = (b * 整数) + 余り
```

と解釈される。

```swift:
-9 % 4 // (4 * -2) - 1 
// -1
-9 % -4 // (-4 * 2) - 1 
// -1
```

また、Float型にも適用可能。

```swift
8 % 2.5 // 0.5
```

### ++, --
それぞれ、1の加算、1の減算となる。
prefixは演算の後に値を返し、postfixは値を返した後に演算を行う。
Swift3.0からは削除されたため、+=演算子、-=演算子などを使って代用する(ただし、これらの演算子は値を返さない)。

```swift:
var a = 0, b = 0
let c = ++a // 1
let d = b++ // 0
```

### +, - (単項)
符号を表す。

## オーバーフロー演算子
### &+, &-, &*
オーバーフローを許容する演算子。

```swift
var i: Int8 = 127 // Int8の最大数
i &+ 1 // -128: Int8の最小数
```

## 比較演算子
### ==, !=, <, >, <=, >=
それぞれ比較の結果のBool値を返す。

### ===, !==
被演算子が同じオブジェクトを参照しているかどうかを判定する。
(被演算子はクラスのオブジェクト)

## 三項条件演算子
### ?:
Swift唯一の三項演算子。

```swift
let isSelected = true

if isSelected {
    print("true")
} else {
    print("false")
}
// ↓同じ
isSelected ? print("true") : print("false")
```

## Nil Coalescing 演算子
### ??
a ?? b (aはオプショナル型)
aがnilのときbを返す演算子。

```swift
let alpha: Int? = nil
let beta: Int = 10

alpha != nil ? alpha! : beta
// ↓同じ
alpha ?? beta
```

## パターンマッチ
### ~=
パターンマッチの結果をBool値で返す。
区間(後述)のマッチによく使われる。

```swift
0...100 ~= 15 // true
```

switch文のcase分岐の際、内部で使われている演算子。

## 区間演算子
両側が整数 → Range<Int>型：for-inに使える。
片側or両側が浮動小数点数 → ClosedInterval型(閉区間)、HalfOpenInterval型(半開区間)：for-inに使えない。

### ...
閉区間：右側の数が含まれる区間。

```swift
0...100 ~= 100 // true
```

### ..<
半開区間：右側の数を含まない区間。

```swift
0..<100 ~= 100 // false
```

## 論理演算子(Logical Operators)
Swiftで論理演算子の被演算子となるはBool型のみ。
### !
論理NOT

```swift:
var isSelected: Bool = true
!isSelected // false
```

### &&
論理AND

|   | 0 | 1 |
|:-:|:-:|:-:|
| 0 | 0 | 0 |
| 1 | 0 | 1 |

(便宜的に、0: false, 1: true)

### ||
論理OR

|   | 0 | 1 |
|:-:|:-:|:-:|
| 0 | 0 | 1 |
| 1 | 1 | 1 |

(便宜的に、0: false, 1: true)

## ビット演算子
整数値を2進数で表したとき、それぞれの桁同士を論理演算した値を返す。

### ~
ビットNOT
それぞれの桁同士にNOT演算。

```swift:
let bit: UInt8 = 0b00001111 // = 15
// ↓
~bit // 0b11110000 = 240
```

(0bは2進数を表すリテラル。)

### &
ビットAND
それぞれの桁同士にAND演算。

```swift:
let bit1: UInt8 = 0b11111100 // = 252
let bit2: UInt8 = 0b11110000 // = 240
// ↓
bit1 & bit2 // 0b11110000 = 240
```
### |
ビットOR
それぞれの桁同士にOR演算。

```swift:
let bit1: UInt8 = 0b11111100 // = 252
let bit2: UInt8 = 0b11110000 // = 240
// ↓
bit1 | bit2 // 0b11111100 = 252
``` 
### ^
ビットXOR
それぞれの桁同士にXOR演算。

XOR演算は以下の表の通り。

|   | 0 | 1 |
|:-:|:-:|:-:|
| 0 | 0 | 1 |
| 1 | 1 | 0 |

(0: false, 1: true)

```swift:
let bit1: UInt8 = 0b11111100 // = 252
let bit2: UInt8 = 0b11110000 // = 240
// ↓
bit1 ^ bit2 // 0b00001100 = 12
```

### <<, >>
ビットシフト演算子
それぞれの桁を右または左に指定した値シフトする。
シフトにより空いた桁を埋める値は、整数型が符号ありか符号なしかで異なる。

+ 符号なし整数(Unsigned Int)

シフトにより空いた桁を0で埋める

```swift
let unsignedInt: UInt8 = 0b11111111 // 255
// ↓
unsignedInt << 4 // 0b11110000 = 240
unsignedInt >> 4 // 0b00001111 = 15
```

+ 符号あり整数(Signed Int)

最上位の桁は符号ビット(the sign bit)といい、0で正、1で負を表す。
符号あり整数の場合、シフトにより空いた桁は符号ビットの値で埋められる。

```swift
let signedPlusInt: Int8 = 127 // 0b0_1111111
signedPlusInt >> 4 // 0b0_0000111 = 7
signedPlusInt << 4 // 0b1_1110000 = -16
// 空いた桁を0で埋めている

let signedMinusInt: Int8 = -127 // 0b1_0000000
signedMinusInt >> 4 // 0b1_1111000 = -8
signedMinusInt << 4 // 0b0_0001111 = 16
// 空いた桁を1で埋めている
```

参考：[マイナス値の2進数での表し方](http://www.geocities.jp/zaqzaqpa/2sinsuu8.htm)

## 複合代入演算子
各々の演算後に、結果を代入する演算子。
### +=, -=, *=, /=, %=, <<=, >>=, &=, |=, ^=, &&=, ||=

```swift
var int: Int = 3

int += 5
// ↓同じ
int = int + 5


var bit: UInt8 = 0b11110000 // 240

bit <<= 4 // 0b00000000 = 0
// ↓同じ
bit = bit << 4
```

## 型チェック、型キャスト
### is
型チェック。
左項のオブジェクトが右項の型に一致すればtrue、異なればfalseを返す。

```swift
let str: Any = "string"
str is String // true
```

### as, as? as!
ダウンキャストを行う。

```swift
let str: String = "string"
str as NSString
```

as!はダウンキャストに失敗した場合、クラッシュする。
as?はダウンキャストに失敗した場合、nilが入る。

```swift
let str: Any = "string"
str as! Int // 実行時エラー
str as? Int // nil
```

# 演算子オーバーロード
既存の演算子の書き換え・定義されてない型への定義。
オーバーロードとカスタム演算子(後述)の導入が可能なのは単項演算子と二項演算子のみ。
書き換えは用法と用量を守りましょう。

```swift
// * を + に書き換え
func * (left: Int, right: Int) -> Int {
    return left + right
}

2 * 3 // 5

// 左側；String、右側：Intに + を定義
func + (left: String, right: Int) -> String {
    return left + String(right)
}

"Number: " + 3 // "Number: 3"
```

# カスタム演算子
新たに演算子を定義。

```swift
// 累乗を計算する演算子を定義
infix operator ** { associativity left precedence 161 }
func ** (left: Int, right: UInt) -> Int {
    var powered = 1
    for _ in 0..<right {
        powered *= left
    }
    
    return powered
}

2 + 3 ** 2 // 11
```

# 参考文献

The Swift Programming Language
https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/BasicOperators.html#//apple_ref/doc/uid/TP40014097-CH6-ID60
https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/AdvancedOperators.html
https://developer.apple.com/library/prerelease/ios/documentation/Swift/Reference/Swift_StandardLibrary_Operators/index.html#//apple_ref/swift/opfunc/s:ZFSsoi2teuRq_Ss9Equatable_FTq_q__Sb

開発のプロが教える-Swift標準ガイドブック
http://www.amazon.co.jp/開発のプロが教える-Swift標準ガイドブック-渡辺-龍司/dp/4839953546

# おわりに
Qiita初投稿でした！楽しかったです！

"プログラミングガイドを読むべし"みたいな話を何度か聞いたことがあったのですが、「参考書の方が速く読めるし、物によるけど説明も丁寧だし、、」と敬遠してきました。
今回初めてプログラミングガイドにしっかりと目を通し、「全部書いてある...。(当然)」と。
原典にあたる大切さを実感として得ることができました。

ビット演算子等まだ理解が及ばない部分も多いので、間違い等ありましたらご指摘下さい。


こういったイベントに積極的に参加する会社っていいですね！(宣伝)