書いて覚えるSwift入門

第51回Swiftの5年間を振り返る

Swift 5周年

Swift Version 1のリリースとほぼ同時期のSoftware Desig 2014年12月号から続いてきた本連載ですが、次回で終了します。ソースコード非互換な変更もいとわなかったSwiftも、Version 5をもってABIも安定化され、言語として一応の完成を見たというのがその一番の理由です。

WWDC19はそれを再確認する場でもありました。とくに図1SwiftUIというSwiftオンリー、すなわちObjective-Cからはもはや使えないFrameworkは「変わらぬ保証」があってはじめて成立すると言っても過言ではありません。

図1 SwiftUI
図1 SwiftUI

今回ではSwiftはどう進化してきたかを振り返り、最終回である次回で今後どう進化していくのかを考察することにしましょう表1⁠。

表1 Swiftのバージョンと環境側の対応
DateVersionComment
2014-09-091.0
2014-10-221.1
2015-04-081.2
2015-09-212.0
2015-10-212.1
2016-03-212.2Open-Sourced
2016-09-133.0Playgrounds for iPad
2017-09-194.0
2018-03-294.1
2018-09-174.2
2019-03-255.0ABI Stability

What's in

何につけ進化について調べるということは、その過程で何が入り何が出たか調べることを意味します。まずは入ったものを見ていきましょう。

"""

かつてSwiftで複数行にわたる文字列リテラルを記述する方法は用意されておらず、

Swiftの例
var text = [
    "zero",
    "one",
    "two",
    "three"
].joined(separator:"\n")

のようにする必要がありましたが、Swift 4以降ではPython同様、

Swift 4の例
var text = """
    zero
    one
    two
    three
"""

と書けるようになりました。

try! Swift // you couldn't

try! Swiftといえば今ではもっとも有名なSwiftカンファレンスですが、実はSwift 1には存在しない概念でした。多くの言語で例外処理は、

JavaScriptの例
try {
    // 例外が発生する可能性がある処理
} catch {
    // 例外が発生した場合の処理
}

という書き方をしますが、Swiftの特徴はtryをブロックの指定ではなく例外をthrowする関数を明示するために使った点。throwsが定義された関数を呼び出す際には必ずtrytry!try?しなければならないため、どこで例外が発生したかがわかりやすいうえ、

Swiftの例
let result = try? throwable()

のように例外が発生したことだけわかればいい場合は、catchを不要にもできる点が便利です。

indirect enum

連結リストの実装を考えてみます図2⁠。

図2 連結リスト
図2 連結リスト

Cであれば、

C言語の例
struct linkedlist {
    VALUE_T value;
    struct linkedlist *link;
};

といったところでしょうか。ところがこれと同じことをSwiftでやろうとすると……、

Swiftの例
struct LinkedList<T> {
    var value:T? = nil
    var link:LinkedList<T>? = nil
}

error: value type 'LinkedList<T>' cannot have a stored property that recursively contains itと怒られてしまいます。値型のstructではなく参照型のclassに変えるとエラーはなくなり、実装上もCなどと同じになりはするのですが、参照型だとme.link = linkのような循環参照も許されてしまいます。Swift 2でindirect指定が加わったことにより、次のように書けるようになりました。

Swift 2の例
indirect enum LinkedList<T> {
    case Some(T, LinkedList<T>)
    case Nil
}

What's out

次に出て行ったものを見てみましょう。

++ --

かつてはSwiftにも++および--演算子が存在しましたが、Swift 3でなくなりました。Swiftはカスタム演算子を実装できるので、次のようにすれば再定義が可能ではありますが、ヒューマンエラー++するのは得策ではないでしょう。

かつてのSwiftの例
prefix func ++<N:Numeric>(_ n:inout N)->N {
    n += 1
    return n
}
今のSwiftの例
postfix func ++<N:Numeric>(_ n:inout N)->N {
    let r = n
    n += 1
    return r
}

引数のvar

かつてのSwiftでは、引数をvar指定することで次のような書き方が許されていました。

かつてのSwiftの例
func fact(_ n:var Int) -> Int {
    var r = 1
    while 0 < n {
        r *= n
        n -= 1
    }
    return r
}

なお、var指定はinout指定とは異なることに注意してください。inoutの場合は呼び出し元も書き換わりますし、呼び出す際には&を変数名につけてその旨を明示する必要があります。

このようにinoutと紛らわしいうえ、エラーも誘発しやすいということで、inout指定されていないSwiftの引数はすべて(強いて言うなら)letになりました。どうしても引数を書き換えたいというのであれば、次のようにコピーを取ってからすればいいのですし。

今のSwiftの例
func fact(_ n:Int) -> Int {
    var r = 1
    var t = n
    while 0 < t {
        r *= t
        t -= 1
    }
    return r
}

Cスタイルのfor;;ループ

ここまで来れば、かつてのSwiftに、

for var i = 0; i < ary.count; i++ {
  let v = ary[i]
  // ...
}

という構文があったことも驚かないでしょう。もちろんこれは、

for v in ary {
    // ...
}

と書いたほうがずっとわかりやすいですし、一般的なfor(foo; bar; baz){ quux }

foo
while bar {
  quux
  baz
}

と書けるのですからなくても困りません。

foreach相当の、コレクションの各要素を順繰りに処理する構文を持つ言語ではCスタイルのforは避けるべきとされつつも廃止までしていないのに対し、バッサリ切ってしまうのがSwiftyですね。

Nothing more to take away

Swiftの進化を最も特徴づけているのは、何を加えたかではなく何を捨てたか。Swiftほど捨てっぷりがいいプログラミング言語を筆者は知りません。とくに構文は一度捨てると下位互換性は確実に失われるため、非推奨になっても居座り続け、捨てるためには別言語にするしかないというのがプログラミング言語業界の常識にすら感じますが、SwiftはあくまでSwiftだというところが不思議でもあります図3⁠。

図3 何も捨てない結果
図3 何も捨てない結果

「完璧なのは、これ以上付け加えるものがなくなったときではなく、これ以上取り除くものがなくなったとき」と言ったのはサン=テグジュペリだそうですが、その意味で5以降のSwiftから何かを取り除くのは格段に難しくなったのは確かです。

次回予告

次回はいよいよ最終回。プログラミングという行為の未来を、Swiftを通して考察する予定です。

Software Design

本誌最新号をチェック!
Software Design 2022年9月号

2022年8月18日発売
B5判/192ページ
定価1,342円
(本体1,220円+税10%)

  • 第1特集
    MySQL アプリ開発者の必修5科目
    不意なトラブルに困らないためのRDB基礎知識
  • 第2特集
    「知りたい」「使いたい」「発信したい」をかなえる
    OSSソースコードリーディングのススメ
  • 特別企画
    企業のシステムを支えるOSとエコシステムの全貌
    [特別企画]Red Hat Enterprise Linux 9最新ガイド
  • 短期連載
    今さら聞けないSSH
    [前編]リモートログインとコマンドの実行
  • 短期連載
    MySQLで学ぶ文字コード
    [最終回]文字コードのハマりどころTips集
  • 短期連載
    新生「Ansible」徹底解説
    [4]Playbookの実行環境(基礎編)

おすすめ記事

記事・ニュース一覧