Swiftに今後追加される言語仕様について調べてみた

  • 53
    いいね
  • 3
    コメント
この記事は最終更新日から1年以上が経過しています。

mixiグループアドベントカレンダー25日目です!

はじめに

モバイルグループの田代です!
最近新規画面はSwiftで書いてます!
そのおりにSwift3.0の話がチーム内ででたので、そのあたりを調べてみました!

概要

Swiftがgithubで公開されAppleだけでなく開発者もSwiftの言語仕様にコミットできるようになりました
それがSwift-Evolutionです!
現在(2015/12/24)でも提案された8つの新仕様がAcceptedとなりSwift2.2やSwift3.0で導入する予定となっています
今回はどういった仕様が追加されていくのか見ていきたいと思います

Proposal

Proposalとは

新仕様の提案書です
上記リポジトリに0000-template.mdというフォーマットが用意されており、それを元に提案したい仕様をまとめてコミットしレビューしてもらい、導入するか否かを決めてもらいます

Proposals

SE-0001: Allow (most) keywords as argument labels (Accepted)

概要

inout,var,let を除いた単語を引数ラベルとして設定できるようにする

Xcode7.2
func hoge(in:String) {   /// Error:Expected ',' separator
}

たとえば上記のように in を仮引数のラベルに設定するとXcode7.2ではエラーになります
ただこれはバグらしく、修正コミットがこちらにあります
https://github.com/apple/swift/commit/c8dd8d066132683aa32c2a5740b291d057937367
こうやって変更点をコードで確認できるのはうれしいですね

SE-0002: Removing currying func declaration syntax (Accepted)

概要

Swiftにはカリー化のための専用の宣言方法がある(初めて知った!)のですが、わかりづらいから削除しようとのことらしいです

Xcode7.2
// Before:
func curried(x: Int)(y: String) -> Float {
  return Float(x) + Float(y)!
}

// After:
func curried(x: Int) -> (String) -> Float {
  return {(y: String) -> Float in
    return Float(x) + Float(y)!
  }
}

上記のProposalの例はどちらもXcode7.2では動きますが今後はBeforeはなくなるようです

SE-0003: Removing var from Function Parameters and Pattern Matching (Accepted)

概要

関数パラメーターとパターンマッチングからvarを削除するとのことですが、よくわからないので例文を見ていきます
例示は理解の試金石ですね

Xcode7.2
func foo(i: Int) {
  i += 1 // illegal
}

func foo(var i: Int) {
  i += 1 // OK
}

上記の例文ではiがimmutableになっているのに再代入しようとしてエラーになってしまいます
Proposalでは他にもif,while,guard,switch,forなどの例があり、どれも変数をimmutableに宣言することによってその後に変数を変更しようとするとエラーになってしまうことが列挙されています

パターンマッチングの例も書いてあったのですが、なにがパターンマッチングなのか判然としなかったので詳しい人がいたら教えてほしいですm(_ _)m

上記solutionとして提示されているのは

  • All function parameters are either unannotated constants or are marked with inout.
  • Only if let is allowed, not if var.
  • Only guard let is allowed, not guard var.
  • Only while let is allowed, not while var.
  • Only case .Some(let x) is allowed, not case .Some(var x).
  • Only for x in is allowed, not for var x in.

となっており、基本的にimmutableとして扱い、mutableにしたい場合は

if let x = getOptionalInt() {
  var x = x
  x += 1
  return x
}

と一度置き換えるようです

SE-0004: Remove the ++ and -- operators (Accepted)

概要

簡単にいえば++--のオペレーターを廃止しようということです
理由としてはx++++xで値の返り値が違うけどあんまり気にしてないよね?ということらしいです

var i=0
i += 1 /// 1

ではどうやってincrementやdecrementを表現するのかといえば上記のようにするようです
ただ代替案も提示されていてx++++xはどちらも同じ結果が変えるようにするということですが、
最終的にどうなるかは気になるところです
ちなみにPythonには++--のオペレーターはないそうです

SE-0005: Better Translation of Objective-C APIs Into Swift (Accepted)

概要

Swift内でのObjective-CのAPIをよりよく置き換えるとのことですが、これは例を見たほうがわかりやすいと思うのでPoposalの例を見てみます

swift2.0
class UIBezierPath : NSObject, NSCopying, NSCoding {
  convenience init(ovalInRect: CGRect)
  func moveToPoint(_: CGPoint)
  func addLineToPoint(_: CGPoint)
  func addCurveToPoint(_: CGPoint, controlPoint1: CGPoint, controlPoint2: CGPoint)
  func addQuadCurveToPoint(_: CGPoint, controlPoint: CGPoint)
  func appendPath(_: UIBezierPath)
  func bezierPathByReversingPath() -> UIBezierPath
  func applyTransform(_: CGAffineTransform)
  var empty: Bool { get }
  func containsPoint(_: CGPoint) -> Bool
  func fillWithBlendMode(_: CGBlendMode, alpha: CGFloat)
  func strokeWithBlendMode(_: CGBlendMode, alpha: CGFloat)
  func copyWithZone(_: NSZone) -> AnyObject
  func encodeWithCoder(_: NSCoder)
}
swift3.0
class UIBezierPath : Object, Copying, Coding {
  convenience init(ovalIn: CGRect)
  func moveTo(_: CGPoint)
  func addLineTo(_: CGPoint)
  func addCurveTo(_: CGPoint, controlPoint1: CGPoint, controlPoint2: CGPoint)
  func addQuadCurveTo(_: CGPoint, controlPoint: CGPoint)
  func append(_: UIBezierPath)
  func reversing() -> UIBezierPath
  func apply(_: CGAffineTransform)
  var isEmpty: Bool { get }
  func contains(_: CGPoint) -> Bool
  func fillWith(_: CGBlendMode, alpha: CGFloat)
  func strokeWith(_: CGBlendMode, alpha: CGFloat)
  func copy(zone _: Zone = nil) -> AnyObject
  func encodeWith(_: Coder)
}

要点としては

swift_name属性の適用を一般化する

swift_name の存在をいま知ったわけですが、Objective-CにSwiftのための名前を定義できる仕組みのようです

// @see https://github.com/apple/swift/blob/master/test/ClangModules/attr-swift_name.swift

// CHECK: warning: too few parameters in swift_name attribute (expected 2; got 1)
// CHECK: + (instancetype)testW:(id)x out:(id *)outObject SWIFT_NAME(ww(_:));

いまはenumやファクトリーメソッドのリネームにしか許可されてないけどCやObjective-Cの実体(entity)?の任意のリネームもできるようにしようということらしいです

冗長な型名の切り落とし

SwiftAPIのガイドラインに合わせて、不要な単語を省略しよう

public mutating func removeElement(member: Element) -> Element? /// bad

public mutating func remove(member: Element) -> Element? /// good

デフォルト引数を追加する

SwiftにAPIをインポートするとき、デフォルト引数に必要なヒントあれば推論してくれるようにする

一番初めの引数にラベルを追加する

メソッドの最初のパラメーターがデフォルト値が設定されていたら、そのメソッドのためにラベルを設定しようとのことです
https://swift.org/documentation/api-design-guidelines.html#first-argument-label

ブーリアン型のプロパティにはisを前につける

Objective-Cのガイドラインではisを接頭語としてつけるのは禁じられていましたが、Swiftのガイドラインに合わせようということらしいです

FoundationAPIsのNSプレフィックスは除去する

クロスプラットフォームAPIにプレフィックスは時代錯誤っぽいのでやめようって話みたいです

詳細はProposalに書いてあるのでそちらを見てほしいのですが、
これは最終的には開発者にも影響あるのですが、まずはApple内でのObjective-Cの規約のような感じもします

SE-0006: Apply API Guidelines to the Standard Library (Awaiting Review)

概要

これはSwift3.0向けのガイドラインをまとめようぜという話らしく、ひとまずアプリ開発者には関係なさそうです

SE-0007: Remove C-style for-loops with conditions and incrementers (Accepted for Swift 3.0)

概要

Cライクなfor-loopを削除しようとのことです
理由としてはfor-instrideがSwiftらしい同じような価値を提供してくれるし、for-inのほうがfor-loopsに比べて文字数が少ないし、SE-0004でもあったけど++などのoperator削除されるから、などの理由が挙げられてました

for (var i=0; i<10; i++) {
  //-- anything
}

ちなみにC-style for-loopは上記みたいな構文です

SE-0008: Add a Lazy flatMap for Sequences of Optionals (Accepted for Swift 2.2)

概要

現在flatmapには二種類あって(詳しくはkoherさんの記事をどうぞ)Optionalをとるものとそうでないものがあります
それがそれぞれで.lazyしたときの挙動が違うので治そうということみたいです

Xcode7.2
[1, 2, 3]
  .lazy
  .flatMap { n in n..<5 }
// LazyCollection<FlattenBidirectionalCollection<LazyMapCollection<Array<Int>, Range<Int>>>>

(1...10)
  .lazy
  .flatMap { n in n % 2 == 0 ? n/2 : nil }
// [1, 2, 3, 4, 5]

終わりに

ざっとReview済みのProposalを見てきましたが、既存のObjective-C周りにも言及されていて、SwiftのNSRangeまわりではまった自分としてはそのあたりも使いやすくなってくれるとうれしいです

この投稿は mixiグループ Advent Calendar 201525日目の記事です。