RxSwift で Observable<T?> を Observable<T> にフィルターしたい

## Observable<T?> を Observable<T> にフィルターしたい


RxSwift 5.0 で、`compactMap` が追加されたことでカンタンにフィルターできるようになりました :tada: 

```swift
let sequence: Observable<Int?> = Observable.of(1, nil, 3)
let compact: Observable<Int> = sequence.compactMap { $0 }
```

@mtgto [コメント](https://qiita.com/takehito-koshimizu/items/fd53fa1363a61492c943#comment-a3934ce0bef902efcdf8)ありがとうございます！
タイトルの内容を実現するだけなら上記の通りで OK です :+1:

以下の内容をそのまま利用することは無くなりましたが、
制約付きで拡張するテクニック自体は使えるので、記事として残しておきます :bow:

---

## はじめに

『Observableとは何か』という概念を理解した後も、
Rx に慣れるまでは、どのようにコードを書けば簡潔に表現できるのか悩むことも多いと思います。

Rx を使わない Swift で簡単だった操作も、Rx を使った途端に記述が複雑になることがあります。
たとえば、`T?` から `T` を取り出したい場合はケースバイケースで下記の方法で値を取り出します。

* Forced Unwrapping
* Optional Binding
* Optional Chaining

Swift によく慣れていれば、この選択に悩むことはあまり無いのではないかと思います。
では、 `Observable<T?>` を `Observable<T>` にフィルターしたい場合はどうでしょうか。

本記事では、再利用性の高い処理をメソッド化することで、Rx の記述が簡潔になる場合があることを、`Observable<T?>` を `Observable<T>` にフィルターする操作を例にして示したいと思います。

##### 環境
* Xcode Version 10.2.1 (10E1001)
* [RxSwift 5.0.1](https://github.com/ReactiveX/RxSwift/tree/5.0.1)
* [APIKit 5.0.0](https://github.com/ishkawa/APIKit/tree/5.0.0)
* [Result 38190f0](https://github.com/antitypical/Result/tree/38190f0)

## T? を T のみにフィルターしたい

RxSwift を使っていると Observable のイベント要素 `T?` を `T` のみにフィルターしたいときがあります。
たとえば以下のように `T` から `Observable<S>` への関数 `transform` があり、
この `transform` を使って、`Observable<T?>` から `Observable<S>` を作りたいときです。
  
```swift
func transform(_ t: T) -> Observable<S>
```

```swift
let observable1: Observable<T> = ...
observable1.flatMap(transform) // OK (transform は T から Observable<S> への変換はできる)

let observable2: Observable<T?> = ...
observable2.flatMap(transform) // コンパイルエラー (transform は T? から Observable<S> への変換はできない)
```

`Observable<T?>` も `Observable<T>` にフィルターできれば、`transform` を使って、`Observable<S>` を作ることができます。

## 愚直なコード

まずは愚直にフィルターしてみます。

`T?` から `T` へのアンラップが可能な場合に限り、強制アンラップすることで、
`Observable<T?>` から `Observable<T>` を作ることができます。

```swift
let observable: Observable<T?> = ...

observable.filter { $0 != nil }.map { $0! }.flatMap(transform) 

// OK (Observable<T?> から Observable<T> へ変換されるので、Observable<S> へ変換できる)
```

あるいは、下記のようなコードでも `nil` をフィルターすることができます。

```swift
let observable: Observable<T?> = ...

observable.flatMap(Observable.from(optional: )).flatMap(transform) 

// OK (Observable.from(optional: ) が `nil` のイベントを潰す )
```

いずれにしろ `T?` を `T` のみにフィルターしたいという要求はこれで解決です。

## 愚直なコードの問題点

しかしながら、毎度毎度 `filter { $0 != nil }.map { $0! }` （あるいは `flatMap(Observable.from(optional: ))`）と記述するのは少々抵抗があります。

* 記述が面倒（アンラップしたいだけなのに、都度同じ記述しないといけない）
* 可読性の低下（処理の本質 `transform` 以外のコードが都度記述されてしまう）
* クロージャで色々ごちゃごちゃされるコードが散見するのがイヤ

## 愚直なコードの問題点の解決策

この問題の解決策として `filter { $0 != nil }.map { $0! }`  を１つにまとめたメソッドを追加します。

`Observable<T?>` に `Observable<T>` を返すメソッド `some()` が実装されれば、
下記のように記述することが可能になります。

```swift
let observable: Observable<T?> = ...

observable.some().flatMap(transform) 

// OK (Observable<T?> -> Observable<T> -> Observable<S>)
```

## 愚直なコードを解決

それでは `some()` メソッドを実装します。
まず、下記のような制約付き拡張で `some()` メソッドを追加することを試みます。

```swift
extension Observable where Element==Optional { // コンパイルエラー

    public func some() -> Observable<Element.Wrapped> {
        return filter { $0 != nil }.map { $0! }
    }
}
```

しかし、上述のコードは Optional の型パラメータ `Wrapped` に具体的な型を指定していないため、
コンパイルエラーになります。

代わりに `Optional<Any>` のように具体的な型で固定すればコンパイルエラーを回避することは可能ですが、
型パラメータ  `Wrapped` は柔軟に扱うことができなくなります。

この問題は `Optional` が適合すべきプロトコル `OptionalProtocol` を定義することで解決します。
プロトコルの宣言と適合方法は下記の通りです。

```swift
/// Optional が適合すべき自作のプロトコル
public protocol OptionalProtocol {
    associatedtype Wrapped

    /// `nil` かどうか判定せずに強制アンラップした値を返す（`nil`の場合は停止する）
    @inlinable var unsafelyUnwrapped: Wrapped { get }
    /// `nil` の場合に限り `true` を返す
    var isNone: Bool { get }
}

extension Optional: OptionalProtocol {
    public var isNone: Bool {
        return self == nil
    }
}
```

上述の `OptionalProtocol` に対して制約付き拡張をすることで
Optional 型にも拡張が適用されます。

```swift
extension ObservableType where Element: OptionalProtocol { // OK

    public func some() -> Observable<Element.Wrapped> {
        return filter { !$0.isNone }.map { $0.unsafelyUnwrapped }
    }
}
```

```swift
let observable: Observable<T?> = ...

observable.some().flatMap(transform) // OK
```

これで `T?` を `T` のみにフィルターすることができ、`filter.map` を都度記述する問題も解決できました。

このようにして、オプショナル型のアンラップ処理など、再利用性の高い処理については、
制約付き拡張によってメソッドを追加することで Rx の記述を簡潔にすることができます。

以下、おまけとしてオプショナル型のアンラップ処理以外の拡張の例を挙げてみます。

## [ おまけ ] `Observable<T?>` を更に便利に扱う

`T?` を `T` のみにフィルターするだけでなく、
エラー処理を扱いたい等の理由で `nil` のみにフィルターした Observable が欲しい場合もあるかと思います。
そこで、`T` と `nil` を別々にフィルターした Observable のタプルを取得できるようにします。

```swift
extension ObservableType where Element: OptionalProtocol {

    /// `Wrapped?` を `Wrapped` のみにフィルターした Observable
    public func some() -> Observable<Element.Wrapped> {
        return filter { !$0.isNone }.map { $0.unsafelyUnwrapped }
    }

    /// `Wrapped?` を `nil` のみにフィルターした Observable
    public func none() -> Observable<Void> {
        return filter { $0.isNone }.map { _ in }
    }

    /// `Observable<Wrapped?>` を `Wrapped` と `nil` のイベントシーケンスに分割したタプル
    public func split(replay: Int = 0, scope: SubjectLifetimeScope = .whileConnected)
        -> (some: Observable<Element.Wrapped>, none: Observable<Void>) {
            let shared = share(replay: replay, scope: scope)
            return (shared.some(), shared.none())
    }
}
```

これで、下記のように `split()` で `T` と `nil` のイベントシーケンスを別々に取得することができるようになります。

```swift
let subject = PublishSubject<Int?>()

// `Int` と `nil` のイベントシーケンスを別々に監視してログ出力します
let observable = subject.asObservable().split()
_ = observable.some.debug("💛 some:").subscribe()
_ = observable.none.debug("💜 none:").subscribe()

// 1, nil, 3 の順にイベントシーケンスを発行します
let observer = AnyObserver(subject)
observer.onNext(1)
observer.onNext(nil)
observer.onNext(3)

// デバッグログは下記のように出力されます
// 💛 some: -> Event next(1)
// 💜 none: -> Event next(())
// 💛 some: -> Event next(3)
```

## [ おまけ ] `Observable<Result<T, Error>>` も便利に扱う

`T?` 型の代わりに [Result](https://github.com/antitypical/Result) の `Result<T, Error>` 型をイベント要素とした Observable を扱いたいこともあるかと思います。

`T?` 型では値が `nil` の場合に、その値の `nil` になった原因まで情報の伝搬ができないためです。

Optional のときと同様にして、制約付き拡張で `T` と `Error` のイベントシーケンスを別々に取得出来るようにしてみます。
Result には `Result<T, Error>` 型が適合すべきプロトコル `ResultProtocol` が定義されているので、
これを利用します。

```swift
extension ObservableType where Element: ResultProtocol {

    public func success() -> Observable<Element.Value> {
        return map { $0.result.value }.some()
    }

    public func failure() -> Observable<Element.Error> {
        return map{ $0.result.error }.some()
    }

    public func split(replay: Int = 0, scope: SubjectLifetimeScope = .whileConnected)
        -> (success: Observable<Element.Value>, failure: Observable<Element.Error>) {
            let shared = share(replay: replay, scope: scope)
            return (shared.success(), shared.failure())
    }
}
```

ここで上述の `some()` は先程自作した、 `Observable<T?>` から `Observable<T>` にフィルターするためのメソッドです。 
再利用性がここで発揮されましたね。

## [ おまけ ] APIKitを使った例

[APIKit](https://github.com/ishkawa/APIKit) はAPIリクエストの結果を `Result<T, Error>` 型でコールバックします。
そこで今回は APIKit を例に挙げて上述のメソッドを使用してみます。

下記のような制約付き拡張を作成して、コールバックを `RxSwift.Single<Result<T, Error>>` として扱えるようにします。

```swift
extension Session: ReactiveCompatible {}

extension Reactive where Base: Session {

    func send<Request: APIKit.Request>(_ request: Request) 
    -> Single<Result<Request.Response, SessionTaskError>> {

        return Single.create { [weak base] (event) -> Disposable in
            let task = base?.send(request) { response in
                event(.success(response))
            }
            return Disposables.create { task?.cancel() }
        }
    }
}
```

`SessionTaskError` の場合に, `event(.error(Error))` でイベントシーケンスとしてのエラーで発行していないことに注意してください。

レスポンスの取得成功・失敗を振り分けずに RxSwift.Single のイベント要素として
そのまま `event(.success(response))` で発行しておきます。

こうすることで、 `SessionTaskError` の型情報を失わずにコールバックすることができます。
また、イベントシーケンスがエラーで終了することもなくなります。

これで、以下のように `Response` と `SessionTaskError` を別々のイベントシーケンスとして取得できるようになります。

```swift
/// リクエストのイベントストリーム（SomeRequest は APIKit.Request に適合した構造体か何か）
let request: Observable<SomeRequest> = ...

/// リクエストの結果を value と error のイベントストリームに分割
let response = request.flatMap(Session.shared.rx.send).split()

_ = response.success
    .subscribe(onNext: { /* `SomeRequest.Response` だけが流れてくる */ })

_ = response.failure
    .subscribe(onNext: { /* `SessionTaskError` だけが流れてくる */ })
```

## おわりに

ということで、再利用性の高い処理をメソッドとして追加することにより、
何度も同じような処理を記述せずにスッキリ記述できるようになります。

`Observable<Result<T, Error>>` に追加したメソッドは APIKit に限らず、
Result 型であれば使える処理ですので、なかなか便利なのではないかと思います。
また、 subscribe 時にクロージャ内で Result 型を switch する必要も無くなるので、
クロージャ内の処理もスッキリします。

RxSwift は慣れるまでは、コードがぐちゃぐちゃになりがちですが、
色々と工夫を凝らしてスッキリさせたいですね。