if文をメソッドチェーンにしてしまう

## じょ
何言ってるんだ？というタイトルですがこういうことです。

```swift
let a = 0
ifTrue(a == 0) { print("0") }
    .elseIf(a == 1) { print("1") }
    .else { print("other") }
```

先日メソッドチェーン原理主義という言葉を思いつきまして、メソッドチェーン原理主義者であれば制御構文もメソッドチェーンでなければ許されないのではないかと考え作ってみました。

賢明な皆さまはもうお気づきだと思いますが、このエントリは「特に何の意味もない」エントリです。戯れ言には付き合わないタイプの方はすぐさまお引き取り頂ければ幸いです。

なお、以下のコードはすべてSwift5.1で書かれています。

## 最初の実装

### 糊

メソッドチェーンを行うためにはチェーンを繋ぐ「糊」に当たるものが必要です。今回はこんな感じです。

```swift
enum IfResult {
    case `true`, `false`
}
```
もう既にバカっぽさ全開です。
メソッド群は条件が真のときは`IfResult.true`を偽の時は`IfResult.false`を戻すように作成します。

### 入口

`IfResult`を使って早速メソッドチェーンの起点となる関数を作成します。

```swift
private func doAndTrue(_ f: () -> Void) -> IfResult {
    (f() is Void) ? .true : .false
}

func ifTrue(_ condition: @autoclosure () -> Bool, _ excute: () -> Void) -> IfResult {
    condition() ? doAndTrue(excute) : .false
}
```

頭のおかしすぎる関数が混ざっていますが、`ifTrue(_:_:)`自体は難しくはないですね。
当然のように`doAndTrue(_:)`関数で警告が出ていますが無視しましょう！（後で消えてなくなるのでご安心ください）

### 繋げる

起点はできましたので`IfResult`を拡張してメソッドチェーンが作れるようにしていきます。

```swift
enum IfResult {
    case `true`, `false`
    
    @discardableResult
    func elseIf(_ condition: @autoclosure () -> Bool, _ excute: () -> Void) -> Self {
        self == .false && condition() ? doAndTrue(excute) : self
    }
}
```

`IfResult`を戻したメソッドの条件が真であった場合は以降の処理はすべてキャンセルされます。
ですので、`IfResult`が`false`の時だけ条件を検査し処理するようにします。

さらにもう一つ

```swift
enum IfResult {
    case `true`, `false`
    
    func `else`(_ excute: () -> Void) {
        self == .false ? excute() : ()
    }
}
```

これは簡単ですね。

### できた

では冒頭で提示したメソッドチェーンを実行してみましょう

```swift
func f(_ a: Int) {
    ifTrue(a == 0) { print("0") }
        .elseIf(a == 1) { print("1") }
        .else { print("other") }
}

(0...3).forEach(f)
// prints ...
// 0
// 1
// other
// other
```

ちゃんと動いてますね。

## 改良された実装

ちゃんと動いてはいますが本当にこれでいいでしょうか？
`else(_:)`メソッドが何も戻さないためメソッドチェーンはここで途切れることになります。
次につながるようになっていた方がよさそうです。では次に何を渡せばいいでしょう。
やはり何らかの値を伝播したいですね。
例えば

```swift
let a: String = ifTrue(cond) { "なにか" }.else { "なんだ？" }
```

のような感じです。

メソッドチェーンを次につなげるために先の実装を改良していきましょう。

### 糊

```swift
enum IfResult<Value> {
    case `false`
    case value(Value)
    
    struct IfResultError: Error {}
    func get() throws -> Value {
        guard case let .value(v) = self else { throw IfResultError() }
        return v
    }
}
```
値を持てるようにしました。
また`get()`メソッドで値そのものを取り出せるようにしました。

### 入口
`ifTrue(_:_:)`メソッドを改修します。

```swift
func ifTrue<T>(_ condition: @autoclosure () -> Bool, _ excute: () -> T) -> IfResult<T> {
    condition() ? .value(excute()) : .false
}
```

不格好な`doAndTrue(_:)`が不要になりすっきりしました。

### 繋げる

`elseIf(_:_:)`と`else(_:)`もサクッと実装します。
再掲になる部分は除いています

```swift
enum IfResult<Value> {
    case `false`
    case value(Value)
    
    @discardableResult
    func elseIf(_ condition: @autoclosure () -> Bool, _ excute: () -> Value) -> Self {
        switch self {
        case .false: return condition() ? .value(excute()) : .false
        case .value: return self
        }
    }
    
    @discardableResult
    func `else`( _ excute: () -> Value) -> Self {
        switch self {
        case .false: return .value(excute())
        case .value: return self
        }
    }
}
```

ちょっと長くなってしまいましたがごく素直な実装です。

### できた

新しいメソッドチェーンを見てみましょう。

```swift
func f(_ a: Int) -> IfResult<String> {
    ifTrue(a == 0) { "0" }
        .elseIf(a == 1) { "1" }
        .else { "other" }
}

(0...3)
    .map(f)
    .map { r in Result { try r.get() } }
    .forEach { _ = $0.map { print($0) } }
// prints ...
// 0
// 1
// other
// other
```

問題なく動いています。
完成です。

## 拡張された実装

ホントに完成？
値を取り出すのに`Result`に頼っています。これはちょっとどうかと思います。
なので実装を拡張します。

### もなど

```swift
extension IfResult {
    @discardableResult
    func map<T>(_ transform: (Value) -> T) -> IfResult<T> {
        if case let .value(v) = self { return .value(transform(v)) }
        return .false
    }
    
    @discardableResult
    func flatMap<T>(_ transform: (Value) -> IfResult<T>) -> IfResult<T> {
        if case let .value(v) = self { return transform(v) }
        return .false
    }
}
```

利用例

```swift
func fizzBuzz1(_ i: Int) -> IfResult<String> {
    ifTrue(i < 1) { fatalError("あかんて") }
        .elseIf(i.isMultiple(of: 3) && i.isMultiple(of: 5)) { "FizzBuzz" }
        .elseIf(i.isMultiple(of: 3)) { "Fizz" }
        .elseIf(i.isMultiple(of: 5)) { "Buzz" }
        .else { String(i) }
}

(1...100)
    .map(fizzBuzz1)
    .forEach { $0.map { print($0) } }
```

```
＿人人人人人人人人人＿
＞　突然のFizzBuzz　＜
￣Y^Y^Y^Y^Y^Y^Y^Y^Y^￣
```

### 比較

ついでなので`Equatable`にしておきましょう。
`Value`の型が`Equatable`でないと比較することができないので制約付きの`extension`になります。

```swift
extension IfResult: Equatable where Value: Equatable {
    static func == (lhs: Self, rhs: Self) -> Bool {
        switch (lhs, rhs) {
        case (.false, .false): return true
        case let (.value(v1), .value(v2)): return v1 == v2
        default: return false
        }
    }
}
```

## まとめ

突然の思い付きにしてはよくできたのではないでしょうか？
関数は可能な限り1つのメソッドチェーンで完結するように書いています。
いくつか難しいものがあり妥協がたくさんありました。
真のメソッドチェーン原理主義者様ならそれらもメソッドチェーンで書くのでしょう。


### 告白
最後に真実を告白させていただきます。
実は私はメソッドチェーン原理主義者ではありません。
ですのでこのエントリで作成したメソッド群は使うことはないでしょう。
使う人がいるのかも疑問です。

ちゃんと最初に「特に何の意味もない」戯れ言だって断ってるからね？
怒っちゃだめよ。