読者です 読者をやめる 読者になる 読者になる

Swift ファーストインプレッション

とりあえずThe Swift Programming Language読んで、実際に自分で少し書いてみた感想。

諸事情でAppleiOSデベロッパーとしてお布施していたので Xcode6beta落として少し書いてみた。プロジェクトスケルトンをswiftで生成できるので、そのコードを眺めたりしていた。

ファーストインプレッション

Immutable脳の人が設計したっぽい。 スクリプト言語っぽい構文に、型注釈。これはGoとシンタックス上の設計思想が似ているんだと思う。

基本的にImmutableな設計でありながら、オブジェクト指向を採用しており、Scalaっぽいマルチパラダイム感がある。Scalaの人は好きになりそう。

型推論のおかげで動的型付け言語触ってきた人にも抵抗がない感じになってる。推論のおかげで静的型付け言語が動的型っぽくみえるのはHaskellとかOCaml方面の雰囲気。

LLVMレジスタの値が不変だと最適化しやすいので、それにあわせてる気がする。どうせ中はLLVMだろう。

気になった機能

let が immutableで var が mutable

let implicitInteger = 70
let implicitDouble = 70.0
let explicitDouble: Double = 70

let式は成功/失敗の値を返す

if let actualNumber = possibleNumber.toInt() {
    println("\(possibleNumber) has an integer value of \(actualNumber)")
} else {
    println("\(possibleNumber) could not be converted to an integer")
}

Dictionary式。JSONっぽいけど違う。

var occupations = [
    "Malcolm": "Captain",
    "Kaylee": "Mechanic",
]
occupations["Jayne"] = "Public Relations"

StructualSubtypingできるのかなぁ。

生のアドレス触る手段もある。

func swapTwoInts(inout a: Int, inout b: Int) {
    let temporaryA = a
    a = b
    b = temporaryA
}

var someInt = 3
var anotherInt = 107
swapTwoInts(&someInt, &anotherInt)”

関数表記はML風っぽい。引数名が必須という点ではTypeScriptとかあの辺にも似てる。

var mathFunction: (Int, Int) -> Int = addTwoInts

func greet(name: String, day: String) -> String {
    return "Hello \(name), today is \(day)."
    }

greet("Bob", "Tuesday")

調べた感じ暗黙のreturnはない

func makeIncrementer() -> (Int -> Int) {
  ...
}

Goといい、関数をfuncと表記するのが流行りなのかな。javascriptにおけるfunctionの面倒臭さの反省のような気もする。

タプルでリターン。

func getGasPrices() -> (Double, Double, Double) {
    return (3.59, 3.69, 3.79)
}

switch式でのパターンマッチ

let somePoint = (1, 1)
switch somePoint {
case (0, 0):
    println("(0, 0) is at the origin")
case (_, 0):
    println("(\(somePoint.0), 0) is on the x-axis")
case (0, _):
    println("(0, \(somePoint.1)) is on the y-axis")
case (-2...2, -2...2):
    println("(\(somePoint.0), \(somePoint.1)) is inside the box")
default:
    println("(\(somePoint.0), \(somePoint.1)) is outside of the box")
}

とか

let yetAnotherPoint = (1, -1)
switch yetAnotherPoint {
case let (x, y) where x == y:
    println("(\(x), \(y)) is on the line x == y")
case let (x, y) where x == -y:
    println("(\(x), \(y)) is on the line x == -y")
case let (x, y):
    println("(\(x), \(y)) is just some arbitrary point")
}

クラス宣言にはC#っぽさも感じる

class GameScene: SKScene {
    override func didMoveToView(view: SKView) {

このコードでエラーが出た。

class Point {
    var x : Int
    var y : Int
    init(){
        self.x = 0
        //self.y = 0
    }
}

initで必ずyも初期化しろとのこと。null安全志向。 newはないので Point() みたいに用いる。Pythonと似ている。クラス専用キーワードのせいでメタプロし辛いのがこれで解決するかもしれない。

デストラクタとして deinit もある。

初期化

class Player {
    var tracker = LevelTracker()
    let playerName: String
    func completedLevel(level: Int) {
        LevelTracker.unlockLevel(level + 1)
        tracker.advanceToLevel(level + 1)
    }
    init(name: String) {
        playerName = name
    }
}
player = Player(name: "Beto")

オブジェクトリテラルっぽい引数渡し

メンバ修飾。これはC#と同じ。。

var simpleDescription: String { get }

protocol 宣言 で実装付インターフェースが作れる。要はtrait

protocol P {
    var z : Int {get; set}
    mutating func adjust() {
        z += 10
    }
}

副作用を起こすときはmutatingキーワードが必要。このケースでは要らんかった

enumが賢い。HaxeEnum思い出した。 パターンマッチができて、メソッドも生やせる。

enum ServerResponse {
    case Result(String, String)
    case Error(String)
}
 
let success = ServerResponse.Result("6:00 am", "8:09 pm")
let failure = ServerResponse.Error("Out of cheese.")
 
switch success {
case let .Result(sunrise, sunset):
    let serverResponse = "Sunrise is at \(sunrise) and sunset is at \(sunset)."
case let .Error(error):
    let serverResponse = "Failure...  \(error)"
}

Optional Chaining

if let johnsStreet = john.residence?.address?.street {
    println("John's street name is \(johnsStreet).")
} else {
    println("Unable to retrieve the address.")
}

CoffeeScriptにあるやつだ。相手がnullableな場合、アクセス不可な場合チェインが途切れてfailする。くっそ便利。

TypeAlias

typealias Point = (Int, Int)
let origin: Point = (0, 0)

ほう

あとで調べる

  • !. アクセッサー
  • unowned 修飾
  • @lazy 修飾。C#のasync相当にみえる。じゃあawait相当のものもある?
  • extension traitっぽい。protocolをmixinするもの?
  • subscript 値の監視や言語組み込みのオブザーバー?面白そうな気配がする。

最高な点

  • 驚き最小
  • まともに動く!!!!

全体的によく練られた良い設計だと思う。

残念な点

  • ネームスペースがない。SpriteキットがSKNodeみたいな感じで使わざるをえない。
  • Appleロックイン。ポテンシャルが高い言語なのでアップルエコシステム以外にも貢献できるはず

こんな感じです。スクリプト言語みたいに軽く扱えるようになってほしい。そんでライブラリマネージャ出てほしい。それなりにコード書いたらまた印象変わると思う。