本文へスキップ
Hironobu Iga

Swift における Void と空 Tuple

Void は空 Tuple の typealias である、というところから出発して、両者がどう振る舞うかを整理したメモです。

公開日

この記事は別サイトにも掲載しています。 https://iganin.hatenablog.com/entry/2019/02/05/020129

はじめに

本日、UZUMAKI さん主催の「iOS アプリ設計パターン入門」の勉強会に参加しました。

内容は MVVM アーキテクチャに関してでしたが、議論の中で Void や () の扱いに関して面白いものがでてきたので備忘もかね記載します。

環境設定

以下の環境を使用しています。

  • Xcode 10.0
  • Swift 4.2

Void と空 Tuple について

Void は以下の形式で表される「型」です。

public typealias Void = ()

そのため、メソッドの引数等にとることはできません。その際には Instance を入れる必要があります。 多くの場合、このような場合の引数として () を使用すると思います。

let sampleRelay = PublishRelay<Void>()

// このように Void で型指定されている部分に ( ) を入れる。
sampleRelay.accept(())

ただ、Void が () の typealias であることから、以下のように () は型としても機能します。

let a: () = ()

また、Void は型であるため以下のようにインスタンス化も可能です。

let a = Void()

したがって、() を代入する箇所では Void() の代入でも代替可能です。 ただ、Void() はできますが、()() はできません。Cannot call value of non-function type '()' というエラーが表示され、コンパイルエラーとなります。

まとめ

以上、取り止めがないですがまとめると下記のようになることがわかりました。

// Void は 型、 () は型としてもインスタンスとしても機能する

let a: () = ()  // OK
let b = ()  // OK
let c = Void() // OK
let d: Void = () // OK
let e = ()() //  NG
let f: () = ()() //  NG

この辺りの言語仕様は普段あまり意識しませんが、色々触ってみると面白いですね。 個人的には Void がインスタンス化可能であることが意外でした。