2017年9月からいよいよSwiftはバージョン4にメジャーバージョンアップを遂げました。
長らく使われてきた3シリーズに比べてかなりの機能が追加されています。
そこでここでは、Swiftのバージョン3と4を徹底比較し、サンプルコードも交えて紹介していくことにします。
内容は以下の通りです。
- Swift4とSwift3の比較
- Swift4のサンプルコード
- 残された課題
Swiftが4から3にかけてどのように変わってきたかについて解説すると共に、Swift4では実現されなかった、Swift5へ向けての課題なども紹介していくことにします。
Swift4とSwift3の比較
まずはSwift3とSwift4の大まかな比較をしていくことにしましょう。
Swiftは、バージョンアップに際し仕様が非常に大きく変わる言語として知られています。
逆に言えば、まだまだSwiftはダイナミックな進化の途上の言語であり、これからもどんどん変わっていく可能性があることを意味します。
しかしその変化にはちゃんと理由があります。まずはそこを理解することから話を始めましょう。
SwiftはSmalltalkを目指す
実はアップル社がObective-Cの時代から一貫して目指してきたものがあります。
それが究極の目標であるSmalltalkに近づくことです。
Smalltalkとは、Xeroxのパロアルト研究所(PARC)においてアラン・ケイ(Alan Kay)らによって開発されたオブジェクト指向プログラミング言語および開発環境のことです。
驚くべきことにこれが開発されたのが1970年代、現在から40年以上も前の話なのです。
アラン・ケイは、SmalltalkだけではなくGUIとマウスの組み合わせのOSやレーザープリンターなど、現在のコンピュータの原型になった試みをしています。
しかしこれはあくまでも実験室レベルの話で、これらのシステムは当時余りにも進みすぎていて実用化されることは有りませんでした。
しかしスティーブ・ジョブズはこの研究に触発されMacを開発したのです。
つまり、Objective-Cの時代からアップルの究極のゴールはSmalltalkに近づくことであり、Swiftはそれを究極まで推し進めた言語なのです。
ですから、Swiftのバージョンアップは
・Smalltalkに近づいていくこと
・最新の技術動向に対応すること
の2点がポイントになるとその理由が良く理解できます。
Swift3の特徴
そういった観点からSwiftの変化を見ていくと良くわかることが有ります。
その一つがSwift3以降はC言語やJava言語のような形式のfor文が使えなくなったというものがあります。
例えば、Swift2までは、
for var i = 0; i < 100; i++ { print("\(i)") }
というような表現が出来ましたが、Swift3からはこれが使用できなくなりました。
for i in 0..<100 { print("\(i)") }
このような変化はSmalltalkを究極のゴールとしているから起こった事です。
前述のようなスタイルはC言語ライクな表現方法で、Smalltalkらしい洗練された表現では無いというのがその理由なのです。
ちなみに、「なんだかRubyと似ているな」と思った人もいるかもしれませんが、実はRubyもまたSmalltalkを目指して作られているからなのです。
ただ、Swiftの場合はObjective-Cからの過去の遺産が残っているので、その痕跡を消しつつゴールを目指しているわけです。
なお、Swift3以降のfor文に関して興味のある方は、以下を参考にしてみてください。
Swift4からSwift3で変わったこと
さて、少し前置きが長くなってしまいましたがSwiftの3から4でどのように変化したのかを簡単に説明していきましょう。主要なものを列挙すると以下の通りになります。
(1) Swift3とのソースコードの共存が可能
(2) デフォルトのパラメータがpublicに
(3) 数値比較の型比較が容易に
(4) Stringの強化
(5) データ構造の強化
(6) JSON解析機能を言語使用に取り入れた
(1)に関しては今までも、そして今後もSwift言語の課題となっていくことでしょう。
Swiftは新しい言語と言うこともありまだまだ言語使用が安定しておらず、マイナーバージョンアップのときでさえ前のバージョンとの互換性がなくなってしまうという問題に悩まされているプログラマーは少なくありません。
Swift4の目標はソースコードの安定性の提供、もう一つは、標準ライブラリのABI(Application Binary Interface )安定性の提供です。
ABIの安定とは異なるバージョンの Swift コンパイラでコンパイルしたバイナリがリンクできる状態であるということです。
なおソースコードに関して言えば、Swift3.2からSwift4.0は互換性が実現されています。
次に、(2)~(5)ですが、これは次で実際にソースコードを紹介しながら解説していくことにしましょう。
Swift4のサンプルコード
それでは、実際にサンプルコードを通してSwift4の新しい機能を紹介していきましょう。
ここで紹介できるのはあくまでも一部ですが、Swift3と比べて明らかに便利になった機能ばかりです。
気軽に入力して実行してみてください。
数値比較
まずは、整数の数値比較について説明します。Swift4では、Swift3で厳密に行われていた数値の型チェックの厳しさが緩んでいます。
例えば、Int、Int16、Int32のように、同じ整数型でもビット数が違うとSwift3までは単純に値の比較ができませんでした。
しかし、Swift4では以下のようなコードが実行可能になります。
let iVal: Int = 10 let i32Val : Int32 = 10 let uiVal : UInt = 10 let ui16Val: UInt16 = 10 let ui32Val: UInt32 = 10 if ui16Val == ui32Val { print("equal!") } if iVal == uiVal { print("equal!") } if iVal == i32Val { print("equal!") } if i32Val == ui16Val { print("equal!") }
を実行すると以下のような結果が得られます。
equal! equal! equal! equal!
このようなコードは型が違うためSwift3ではエラーになっていましたが、Swift4では制限が緩和されたため、普通に実行できるようになりました。
文字列(String)の強化
次にStringの強化された点について説明します。いくつかポイントが有りますのでトピックごとに分けて説明していきます。
文字列のコレクション化
Swift3で棚上げにされていた文字列のコレクション化ですが、Swift4になってやっと実現されました。
"SAMURAI".forEach{ // 一文字ずつ取り出し、データとして取得できる print($0) }
実行結果は次のようになります。
S A M U R A I
実行結果から判るとおり、文字列が、一つ一つの文字から構成されるコレクションとして扱うことが出来るので、forEachで一文字ずつ取り出すことがきます。
複数行の文字列定義
Swift4では複数行の文字列を定義できるようになりました。Swift3までは改行コードが必要でしたが、以下のような方法で簡単に複数行の文字列を定義できます。
let str = """ 1234567 qwertyuiop asdfghjkl zxcvbnm """ print(str)
実行結果
1234567 qwertyuiop asdfghjkl zxcvbnm
ちょっとしたことですが、これで文字列を扱う文字列が非常に楽になります。
Subscript
Swift 4では、インデックスを使った便利な文字列の部分取得方法があります。
以下のようにindex(of:)を用いると、単なる数値ではなく柔軟な範囲指定ができます。
let str = "Hello Samurai-Engineer." let hyphen = str.index(of: "-")! let dot = str.index(of: ".")! let space = str.index(of: " ")! print(str[..<hyphen]) // "Hello Samurai" print(str[..<dot]) // "Hello Samurai-Engineer" print(str[..<space]) // "Hello"
このプログラムの実行結果は以下の通りです。
Hello Samurai Hello Samurai-Engineer Hello
なお、Swift3までのStringについては、以下に詳しく書いてありますので、あわせて読んでみてください。
データ構造の進化
Swift4では辞書(Dictionary)の機能が大幅にアップされたり、配列のようなデータ構造の機能が強化されています。
Swift3まではforやforeachなどを用いなくてはならなかった処理を簡単に出来るようになっているのが特徴です。
以下、それぞれの内容についてサンプルを紹介していきましょう。
Dictionaryのマージ
まずは、Dictionaryのマージサンプルから見てみましょう。Swift4からは、mergeメソッドで辞書同士を結合できるようになりました。
let defaultVals: [String : Any] = [ "Ruby" : 1, "Python" : 2, ] var optionVals: [String : Any] = [ "Ruby" : "rails", "PHP" : "laravel", ] optionVals.merge(defaultVals) { optionValue , defaultValue in return optionValue } print(optionVals)
実行結果は以下の通りです。
["Python": 2, "Ruby": "rails", "PHP": "laravel"]
統合先の値はoptionValue 、統合するデータの値はdefaultValueで定義されています。
optionValsに、defaultValsを追加しますが、統合するための辞書はletではなくvarにする必要があります。
また、クロージャの中ではキーが重複した際の処理方法を指定しています。このサンプルでは重複しているキーはoptionValueを利用するよう指定しています。
mapValues
もともとSwift3までは辞書などのコレクションにはmapが備わっていますが、Swift4には新たにmapValuesが追加され、これによって辞書のようなハッシュコレクションとして使用できるようになりました。
以下に、サンプルを示しますので実行してみてください。
let dic = ["Ruby": 3, "PHP": 2, "Python": 1] // mapValuesで、Valueを2倍にする let mapped = dic.mapValues { $0 * 2 } print(mapped)
["PHP": 4, "Python": 2, "Ruby": 6]
実行結果から判るとおり、辞書であるdicの値だけを一気に2倍にした、mappedを取得できました。
Swift3までなら、このようなことをやろうとするのならばforやforeachを用いて値を取得し2倍にする処理を書かなくてはなりませんでした。
配列要素の入れ替え
また、swap関数を用いて配列の位置を入れ替えるという処理も出来るようになりました。
var fruits = ["apple", "orange", "pineapple", "banana", "strawberry", "cherry"] swap(&fruits[1], &fruits[3]) print(fruits)
実行結果を見ると判りますが、orangeとbananaの位置が入れ替わっています。
["apple", "banana", "pineapple", "orange", "strawberry", "cherry"]
このような機能は地味ですが、かなり便利な機能です。
残された課題
このように大変便利な機能が増えたSwift4ですが、いくつか課題も残されています。
その中で最も大きいのが、ABIの安定です。歴史の浅いSwift言語ですが、それでもたくさんのソフトウェア資産が生み出されています。
したがって、過去の資産を再利用可能かどうかということはSwift言語の今後の発展では非常に重大な問題になってきます。
Apple社はSwift4の間にABIを安定させたい方針ですが、それが実現するかはまだわかりません。
また、このほかにもコンパイラの信頼性向上,エラーメッセージの改善,コンパイル時間のスピードアップなど、取り組むべき課題は山積しています。
まとめ
以上、Swift3と比較しながらSwift4がどのようなものかと言うことを、
・Swift4とSwift3の比較
・Swift4のサンプルコード
・残された課題
という順序で説明してきました。
Swift言語はまだまだ言語としては新しい言語ですがメジャーになってきたことにより成熟期に入り、より使いやすい言語を目指している状態であると言えます。
そしてそれが成功するか否かは、Swift4がどこまで進歩できるかと言うことにかかっているのです。