Swift3.0ではC言語のようなfor文が使えなくなります
Swiftがオープンソースになり、現在のSwift2系からSwift3系にバージョンアップする際にどのようなアップデートがあるかを把握できるようになりました。
バージョンアップに盛り込まれる機能、削除される機能はどのように決められるかというと、以下のような流れで決められているようです。
- 提案
- レビュー
- 採択
これらの提案はApple内部の方だけでなく、Apple社外のユーザーからも提案が可能になっています。
これらの提案の中で特に象徴的なことの一つとして、C-Styleのfor文が削除というものがあったのですが、Swift3.0で削除されることが正式に決まっています。
このproposal(提案)はApple社外のErica Sadun氏からの提案であり、具体的には以下のような構文が使えなくなるということを意味しています。
for var i = 0; i < 100; i++ {
print("\(i)")
}
Objective-Cでもよく使われる構文であり、これがなくなるのはかなりの衝撃だと思います。
おそらくSwiftで書かれているプロダクトコード内にもこのスタイルで書かれた構文がいくつかあると思います。
あまりにも使い慣れた構文であり、これがなくなることによって書けないものもあるんじゃないのか?という疑問も当然浮かんでくるかと思います。
安心してください!書けますよ。
そして、これからSwiftで書くソースコードでこのことを考慮して書いておくだけでSwift3.0が出た際にそれに伴う修正を行う必要がなくなります。
今まではWWDCで発表されるまでどのような変更がなされるか分かりませんでしたが、オープンソース化によって今からでも対策を練ることができます。
サンプル
それではいくつかのサンプルを見てみましょう。
単純なfor文
非常に単純なfor文です。Swift3.0では以下の構文が書けなくなります。
for var i = 0; i < 100; i++ {
print("\(i)")
}
これはfor-in
を使うことで解決できます。以下のコードは上記のコードと同じ意味になります。
for i in 0..<100 {
print("\(i)")
}
また、このような書き方もできます。forEach
についてはこちらの記事にも記載しています。
Array(0..<100).forEach {print("\($0)")}
このような非常に単純なものであれば、従来のfor文よりもより簡潔に書くことができるようになっています。
インデックスを利用したい場合
配列内のインデックスが大きな意味を持つ場合があります。例えば奇数のインデックスの要素のみを取得したい場合はどうでしょうか?
Swift3.0から使えなくなるインデックスの取得
従来の書き方であればこのように書いていたでしょう。
let array = ["a", "b", "c", "d"]
for var i = 0; i < array.count; i++ {
if (i % 2) != 0 {
print("\(array[i])") // b, d
}
}
これまで述べてきたとおり、この文法はSwift3.0では使用できなくなります。しかしSwiftにはenumerate
という便利なメソッドがあります。
enumerate
を使用したインデックスの取得
enumerate
はインデックスと要素のタプルの配列を生成してくれるSequenceType
に定義されたメソッドです。
enumerate
を使用すると、以下のように書くことができます。
let array = ["a", "b", "c", "d"]
for (index, element) in array.enumerate() {
if (index % 2) != 0 {
print("\(element)") // b, d
}
}
for-in
を使用せずに以下のように書くことも可能です。
let array = ["a", "b", "c", "d"]
array.enumerate().filter { ($0.0 % 2 != 0)} .map { $0.1 }
array.enumerate().flatMap { ($0.0 % 2 != 0) ? $0.1 : nil }
map
やfilter
などについてはこちらの投稿で詳しく解説していますのでご参照ください。enumerate
についても触れています。
stride
を利用した方法
インデックスに応じた要素を取得するには、以下のようにstride
を利用する方法も良いかと思います(@uasiのコメントより)。
let array = ["a", "b", "c", "d"]
for i in 1.stride(to: array.count, by: 2) {
print("\(array[i])") // b, d
}
まとめ
**あのfor文がなくなるなんて!**という衝撃はあるものの、map
やfilter
、enumerate
など見慣れなくてとっつきにくいのですが、これらのSwiftの標準ライブラリに用意されているものを利用すれば実はあまり困ることがありません。
従来のfor文を標準ライブラリに用意されているメソッドで書き換えてみようとすると、従来の記述が冗長であることもなんとなくわかってきます。
Swift3.0に向けて今までのfor文を使わないように書き換えていきましょう!
その他参考資料
第2回shibuya.swiftでは、この内容についてLTを行いました。