RxSwift 3.3.0で追加された3つのUnit（Single, Maybe, Completable）

RxSwift 3.3.0で3つのUnitが追加されました。

* `Single`
* `Maybe`
* `Completable` 

RxJavaにあったものが輸入された形のようです。

付属のPlaygroundに例が書かれていなかったので、ざっくりどんなものか確認してみました。
この記事は半分備忘録みたいなものになります。

# 追記
3.4.0で subscription closures (onSuccess, onError, onCompleted) が実装されました。
やっぱり欲しいよね。プルリク投げてくれたfreak4pcさんありがとう。

[Add subscription closures for Single, Maybe and Completable (`onSuccess`, `onError`, `onCompleted`) by freak4pc · Pull Request #1175 · ReactiveX/RxSwift](https://github.com/ReactiveX/RxSwift/pull/1175)


# 概要

まず前提として、 `Observable` は `Completed` あるいは `Error` が流れた時点でそれ以上何も流れなくなりますが、その2つが流れない限り `Next` は延々と流れてくる可能性があります。

それを踏まえて今回追加された3つのUnitについて見てみると、以下の表のようになります。

|  | Single | Maybe | Completable |
|---|---|---|---|
| Success | ○ | ○ | × |
| Completed | × | ○ | ○ |
| Error | ○ | ○ | ○ |

`Success` は 1回だけ流れる `Next` だと思って下さい。
その`Success` が流れるのが `Single` と `Maybe` です。
`Maybe` は `Success` が流れず、 `Completed` のみ流れてくる可能性があります。
`Completable` では `Success` は流れてきません。

# 例

それぞれつくって、実際にどんな風に使えるのか見ていきましょう。

## Single

```Swift
let disposeBag = DisposeBag()

enum MyError: Error {
    case unknown
}

Single<String>
    .create(subscribe: { (observer) -> Disposable in
        observer(.success("🐶"))
        observer(.success("🐱")) // ignored
        observer(.error(MyError.unknown)) // ignored
        return Disposables.create()
    })
    .do(onNext: { (value) in
        print("onNext")
    }, onError: { (error) in
        print("onError")
    }, onCompleted: {
        print("onCompleted")
    }, onSubscribe: {
        // subscribe前に実行される 
        print("onSubscribe")
    }, onSubscribed: {
        // subscribe後に実行される 
        print("onSubscribed")
    })
    .subscribe({ (result) in
        switch result {
        case .success(let value):
            print("success: \(value)")
        case .error(let value):
            print("error: \(value)")
        }
    })
    .disposed(by: disposeBag)
```

### 追記：3.4.0からは次のようにも書けます

```Swift
let disposeBag = DisposeBag()

enum MyError: Error {
    case unknown
}

Single<String>
    .create(subscribe: { (observer) -> Disposable in
        observer(.success("🐶"))
        observer(.success("🐱")) // ignored
        observer(.error(MyError.unknown)) // ignored
        return Disposables.create()
    })
    .subscribe(onSuccess: { (value) in
        print("success: \(value)")
    }, onError: { (error) in
        print("error: \(error)")
    })
    .disposed(by: disposeBag)
```

## Maybe

```Swift
let disposeBag = DisposeBag()

enum MyError: Error {
    case unknown
}

Maybe<String>
    .create(subscribe: { (observer) -> Disposable in
        observer(.completed)
        observer(.success("🐶")) // ignored
        observer(.error(MyError.unknown)) // ignored
        return Disposables.create()
    })
    .subscribe({ (result: MaybeEvent<String>) in
        switch result {
        case .success(let value):
            print("success: \(value)")
        case .completed:
            print("complete")
        case .error(let error):
            print("error: \(error)")
        }
    })
    .disposed(by: disposeBag)
```

### 追記：3.4.0からは次のようにも書けます

```Swift
let disposeBag = DisposeBag()

enum MyError: Error {
    case unknown
}

Maybe<String>
    .create(subscribe: { (observer) -> Disposable in
        observer(.completed)
        observer(.success("🐶")) // ignored
        observer(.error(MyError.unknown)) // ignored
        return Disposables.create()
    })
    .subscribe(onSuccess: { (value) in
        print("success: \(value)")
    }, onError: { (error) in
        print("error: \(error)")
    }, onCompleted: {
        print("complete")
    })
    .disposed(by: disposeBag)
```

## Completable

```Swift
let disposeBag = DisposeBag()

enum MyError: Error {
    case unknown
}

Completable
    .create(subscribe: { (observer) -> Disposable in
        observer(.error(MyError.unknown))
        observer(.completed) // ignored
        return Disposables.create()
    })
    .subscribe({ (result: CompletableEvent) in
        switch result {
        case .completed:
            print("complete")
        case .error(let value):
            print("error: \(value)")
        }
    })
    .disposed(by: disposeBag)
```

### 追記：3.4.0からは次のようにも書けます

```Swift
let disposeBag = DisposeBag()

enum MyError: Error {
    case unknown
}

Completable
    .create(subscribe: { (observer) -> Disposable in
        observer(.error(MyError.unknown))
        observer(.completed) // ignored
        return Disposables.create()
    })
    .subscribe(onCompleted: { 
        print("complete")
    }, onError: { (error) in
        print("error: \(error)")
    })
    .disposed(by: disposeBag)
```

# 所感

今回追加されたUnitは使いたいシーンが結構ありそうです。
今まで `Next` が何回流れるか示したい場合はAppleDoc等で分かるようにしないといけませんでした。1回だけで良いのであれば、 `Single` や `Maybe` を使えば、ドキュメントに記載しなくても意図が明確になります。