ちょっと話題の記事

[Swift 3.0] ++, –がなくなる話

2016.05.09

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

おばんです、映画オデッセイを見て土木建築農業にエンジニアリングと科学を足した最強のTOKIOだという感想を抱いた田中です。

さて、先日友人にSwiftを布教している時こんな話題が挙がりました。

スクリーンショット 2016-05-09 15.05.07

「え、Swiftって++はdeprecateなのかよ...、Swiftェ...」

そう、Swift 3ではdeprecatedになるのは界隈ではよく話題に登ってるかと思います。
しかし理由までは僕も知らなかったので、swift-revolutionのproposals、0004-remove-pre-post-inc-decrement.mdをオレオレ和訳・オレオレ解釈で読んでみることにしました。

訳・意味がおかしい等ありましたら@ktanaka117まで、こっそり教えてください。

以下はそのまとめです。

Remove the ++ and -- operators(++と--のオペレータを除外する)

Introduction(紹介)

インクリメントとデクリメントのオペレータはSwift初期からCの引き継ぎとして追加されました。
これらは熟慮されず、追加されました。
このドキュメントでは新しい見方でこのオペレータについて考え、さらには混乱と重荷の原因となるこれらを除外することを提案します。

くだんのオペレータというのは以下の4つのことです:

let a = ++x  // pre-increment  - returns input value after mutation
let b = x++  // post-increment - returns copy of input value before mutation
let c = --x  // pre-decrement  - returns input value after mutation
let d = x--  // post-decrement - returns copy of input value before mutation

しかしながら、これらのオペレータの結果の値はしばしば見落とされます。

Advantage of These Operators(良い点)

  • ++インクリメントは拡張表現である。x += 1とかx.advance()を短くできる。 - ①
    戻り値が必要だとすれば、+=はVoidを返すのでインラインで書くことができない。 - ②
  • C familyの言語(C++, Objective-C, Java, C#, Javascript, etc)から来た人になじみやすい

Disadvantage of These Operators(悪い点)

  1. Swiftを第一言語として覚える人の重荷になる。
  2. x++で書けるうまみはとても小さい。 x += 1と比べてそんなに変わらない。
  3. Swiftはすでに=や+=、他のVoidを返しアサインする、Cからきたオペレータから脱却している。こういった経緯から++等のオペレータの存在は不適当である。
  4. Swiftは他の言語におけるC-styleのforループで使ってきた++iを排除する。 - ③
  5. ++等のオペレータが使われているコードは読み手やメンテナンス者を混乱させがち。難解でトリッキーなコードを生みがち。
  6. Swiftは明確な評価順序を持っている一方で、foo(++a, a++)などはそれが不明瞭である。
  7. これらのオペレータはいくつかのタイプに当てはまる。数値型を操作するパターンや、イテレータのような使い方などである。複数パターンあることによって複雑になっている。

さいごに、「もし今これらのオペレータがSwiftになかったら、Swift 3にこれらを追加するかどうか?」を考えてみてほしい。

Proposed Approach(提案)

これらのオペレータを言語仕様からなくしたい。
今後の展開の仕方としては、Swift 2.xのバージョンではdeprecateとして、Swift 3では完全に除外したい。

Alternatives considered(考えうる代替案)

一番簡単な代替方法はこれらを残すこと。
よりよく考えると、これらのオペレータをVoidを返すように変えることができる。
この解決策はいくつかの問題が生じるが、一つの問いを紹介する。
一度結果を置いておいたとしても、その違いはprefixとpostfixを除外する。
どちらにせよ、以下の残念な選択をしなくてはならない。

  1. どっちも残すけど、x++と++xの挙動を同じくする
  2. x++と++xどちらかを無くす。C++プログラマーは++xを一般的に好むけど、他はx++を好むだろう。どっちか片方を無くすのはCからの脱却となる。

どちらにしても注意深く考えなくてはならないし、これらのオペレータの複雑性を正当化するには至らない。

注釈

①++インクリメントは拡張表現で、x += 1とかx.advance()を短くできる。

++を使わないパターン

func test(num: Int) {
    print(num)
}

var x = 1
x += 1
test(x)

++を使ったパターン

func test(num: Int) {
    print(num)
}

var x = 1
test(++x)

どちらも結果としては同じだが、やりたいことに対して一行減る。

②+=はVoidを返すのでインラインで書くことができない。

定義元をみると++はIntを返す。+=はVoidを返す。

public func +=(inout lhs: Int, rhs: Int)
prefix public func ++(inout x: Int) -> Int

③SwiftはC-styleのforループで使ってきた++iを排除する。

スクリーンショット 2016-05-09 15.08.28

この++, --の話の他に、Swift 3ではC-styleからの脱却としてforループの除外も行われる。
詳しくはこちらの0007-remove-c-style-for-loops.mdを参照のこと。

まとめ

全体を読んでみてわかったのは

  • C言語からの脱却していきたい
  • 評価順序や読み手にとって不明瞭な箇所を極力なくしていきたい

というところが今後のSwiftで意識したいポイントだから++や--などのオペレータをなくしたいのかなと思いました。

C-styleのforループをなくす話など、その他のproposalに挙がっている内容とリンクしている箇所が多くありそうなので他のものも読んでいくとより理解が進みそうです。

個人的には++と--は便利だし、他の言語から入るひとからしても「あって当然」と思えるところがあるので残してもいいんじゃないかなぁと思いました。
UIにしろ言語にしろ、慣れによる使用感って大事だと思うのでそこを削らなくともーとは思います。