Swift3.0では使い慣れたfor文が使えなくなります

# Swift3.0ではC言語のようなfor文が使えなくなります
Swiftがオープンソースになり、現在のSwift2系からSwift3系にバージョンアップする際にどのようなアップデートがあるかを把握できるようになりました。

バージョンアップに盛り込まれる機能、削除される機能はどのように決められるかというと、以下のような流れで決められているようです。

1. 提案
2. レビュー
3. 採択

これらの提案はApple内部の方だけでなく、Apple社外のユーザーからも提案が可能になっています。

これらの提案の中で特に象徴的なことの一つとして、**C-Styleのfor文が削除**というものがあったのですが、**Swift3.0で削除されることが正式に決まっています。**

* [Remove C-style for-loops with conditions and incrementers](https://github.com/apple/swift-evolution/blob/master/proposals/0007-remove-c-style-for-loops.md)

このproposal(提案)はApple社外のErica Sadun氏からの提案であり、具体的には以下のような構文が使えなくなるということを意味しています。

```swift
for var i = 0; i < 100; i++ {
    print("\(i)")
}
```

Objective-Cでもよく使われる構文であり、これがなくなるのはかなりの衝撃だと思います。

おそらくSwiftで書かれているプロダクトコード内にもこのスタイルで書かれた構文がいくつかあると思います。

あまりにも使い慣れた構文であり、これがなくなることによって書けないものもあるんじゃないのか？という疑問も当然浮かんでくるかと思います。

**安心してください！書けますよ。**

そして、**これからSwiftで書くソースコードでこのことを考慮して書いておくだけでSwift3.0が出た際にそれに伴う修正を行う必要がなくなります。**

今まではWWDCで発表されるまでどのような変更がなされるか分かりませんでしたが、オープンソース化によって今からでも対策を練ることができます。

## サンプル
それではいくつかのサンプルを見てみましょう。

### 単純なfor文

非常に単純なfor文です。Swift3.0では以下の構文が書けなくなります。

```swift
for var i = 0; i < 100; i++ {
    print("\(i)")
}
```

これは`for-in`を使うことで解決できます。以下のコードは上記のコードと同じ意味になります。

```swift
for i in 0..<100 {
    print("\(i)")
}
```

また、このような書き方もできます。`forEach`については[こちらの記事](http://qiita.com/mo_to_44/items/cf83b22cb34921580a52#foreach%E3%81%AFfor-in%E3%82%92%E3%82%88%E3%82%8A%E7%B0%A1%E6%BD%94%E3%81%AB%E8%A8%98%E8%BF%B0%E3%81%97%E3%81%9F%E3%81%84%E6%99%82%E3%81%AB%E4%BD%BF%E3%81%86)にも記載しています。

```swift
Array(0..<100).forEach {print("\($0)")}
```

このような非常に単純なものであれば、従来のfor文よりもより簡潔に書くことができるようになっています。

### インデックスを利用したい場合

配列内のインデックスが大きな意味を持つ場合があります。例えば**奇数のインデックスの要素のみを取得したい場合**はどうでしょうか？


#### Swift3.0から使えなくなるインデックスの取得

従来の書き方であればこのように書いていたでしょう。

```swift
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`を使用すると、以下のように書くことができます。

```swift
let array = ["a", "b", "c", "d"]
for (index, element) in array.enumerate() {
    if (index % 2) != 0 {
        print("\(element)") // b, d
    }
}
```


`for-in`を使用せずに以下のように書くことも可能です。

```swift
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`などについては[こちらの投稿](http://qiita.com/mo_to_44/items/cf83b22cb34921580a52)で詳しく解説していますのでご参照ください。`enumerate`についても触れています。


#### `stride`を利用した方法
インデックスに応じた要素を取得するには、以下のように`stride`を利用する方法も良いかと思います（@uasiのコメントより）。

```swift
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](http://shibuya-swift.connpass.com/event/21979/)では、この内容についてLTを行いました。

* [Swift3.0に向けて enumerateを使い始めよう](http://www.slideshare.net/motokinarita7/swift30-enumerate)