Never GiveUp というタイトルで Swift Tweets で発表しました。 #swtws

![#swtws Never GiveUp.001.png](https://qiita-image-store.s3.amazonaws.com/0/17198/f6ede14e-a85d-0695-b221-c45ef847f908.png)

今回は Swift 3 から登場した `Never` 型で遊んでみたいと思います。

この記事は **Never GiveUp** というタイトルで [Swift Tweets](https://swift-tweets.github.io) で発表したツイートをまとめたものになります。

# Never 型とは

`Never` 型は `fatalError` でも使われる、**戻り値がない** ことを示す型です。

Swift 2 では `@noreturn` 属性でしたが、表から『値を返さないこと』が見えにくいため、Swift 3 からは型として明記されることになったみたいです。

```swift
/////////////////////////////////////////////////////
//// ⭐️ 生還に期待を寄せてしまうコード (Swift 2)

@noreturn func oneWayTrip() -> Gift? {
}

/////////////////////////////////////////////////////
// ⭐️ 戻り値がないことが明確なコード (Swift 3)
//

func oneWayTrip() -> Never {

    // コンパイラーによって、必ず処理が打ち切られることが保証される。
    // ERROR: Function with uninhabited return type 'MyNever' is
    // missing call to another never-returning function on all paths
}

// この戻り値が Never なので、処理はここまで。
oneWayTrip()

// この行には辿り着き得ない。
print("DONE")       // WARNING: Will never be executed
```

その実態は、列挙子のない列挙型は値化できない性質を応用して『値が存在し得ないから打ち止め』みたいな表現です。実際の定義は、このようにシンプルなものになっています。

```swift
enum Never {
    
}
```

# Never は、つくれる？

それなら『もしかして自分で作れる？』と思ってみたのが今日のテーマです。

実際、列挙子を持たない列挙型を定義しただけで、標準の `Never` と同じ動きを見せてくれました。

```swift
enum MyNever {
    
}

func oneWayTrip() -> MyNever {
    
    
    // ERROR: Function with uninhabited return type 'MyNever' is
    // missing call to another never-returning function on all paths
}


// ⭐️ 標準の Never と同じ動作になった

oneWayTrip()
print("DONE")       // WARNING: Will never be executed
```

# 本当に、値化できない？

ところで本当に値化できないのでしょうか。そう思って標準の `Never` にイニシャライザーを拡張して使ってみると、右辺を評価したところ打ち切りに。やはり無理みたいです。

```swift

extension Never {
    
    init() {
        
        self = unsafeBitCast((), to: Never.self)
    }
}

// ⭐️ やっぱりインスタンス化はできない

let never = Never()     // WARNING: Will never be executed
```

じゃあ、イニシャライザーではなく関数ならどうだろうと試してみたのですけど、やっぱりダメそうですね。関数の呼び出しまでで打ち切りです。

```swift
func oneWayTrip() -> Never {
    
    return unsafeBitCast((), to: Never.self)
}

let never = oneWayTrip()        // WARNING: Will never be executed
```

でも、もしかしてオプショナルに包んでみたら…？ と試してみたら、**できました**。オプショナルバインディングで `Never` な値が取れました。子供騙しな感は残りますけれど。

```swift
func oneWayTrip() -> Never? {
    
    return unsafeBitCast((), to: Never.self)
}

if let never = oneWayTrip() {
    
    print("Success !?", never)          // "Success !? \n"
    print("Type is", type(of: never))   // "Type is Never\n"
}
```

それなら `Any` 型は…？ と試してみると、大丈夫みたい。入れ物は `Any` ですが、オプショナルと違ってすぐ使えるし、キャストで正真正銘 `Never` な値になります。

```swift
func oneWayTrip() -> Any {
    
    return unsafeBitCast((), to: Never.self)
}

// ⭐️ 型は Any 
let never = oneWayTrip()

print("Type is", type(of: never))   // "Type is Never\n"
print("Is Never: ", never is Never) // "Is Never: true\n"


// ⭐️ キャストすると純粋な Never 型の値として使える。
let a = never as! Never

print(a)                            // "\n"
```

ジェネリック型だとどうでしょう。何かしらの形で `Never` を指示しないといけないものの、型推論も期待できるので、`Never` を取る関数にそのまま渡せたりします。

```swift
func oneWayTrip<N>() -> N {

    return unsafeBitCast((), to: N.self)
}

let never: Never = oneWayTrip()

print("Never", never)               // "Never \n"
print("Type is", type(of: never))   // "Type is Never\n"


// ⭐️ とりあえず、スマートに Never 型を受け取るところまではできた。
func challange(_ something: Never) {
    
    print(something)
}

// ⭐️ 奇跡の生還
challange(oneWayTrip())

// ⭐️ 処理が継続
print("DONE")       // "DONE"
```

# おしまい

今回はここまで。`Never` を自作したり、列挙子を持たない列挙型を値化したりして遊んでみました。これによってどんな世界が広がるのかは分からないですけど、とりあえず面白かったです。

以上、ありがとうございました！

![#swtws Never GiveUp.002.png](https://qiita-image-store.s3.amazonaws.com/0/17198/1e1ebaeb-da66-0dc5-461f-a3b9dd0218a6.png)

> * [横浜 iPhone 開発者勉強会 #yidev](https://atnd.org/groups/yidev)
> * [カジュアル Swift 勉強会 #cswift](https://atnd.org/groups/cswift)
> * [みんなで Swift 復習会 #yidev](http://cswift.connpass.com)
> * [熊谷と繪面がプログラミングコードの内から聴こえてくる声に耳を傾けて楽しむラジオ](http://mookmookradio.com/a0005/)