Swift

Swift のクロージャが面白い

More than 3 years have passed since last update.

省略記法

Swift のクロージャの基本的な書き方はこう:

let sorted = sort(anArray, { (s1: String, s2: String) -> Bool in
    return s1 < s2
})

型推論が効くので、仮引数の型とカッコ、返り値の型は省略できる:

let sorted = sort(anArray, { s1, s2 in
    return s1 < s2
})

クロージャ本体が式ひとつだけからなる場合、 return も省略できる:

let sorted = sort(anArray, { s1, s2 in s1 < s2 })

プレースホルダを使えばここまで短くなる:

let sorted = sort(anArray, { $0 < $1 })

さらに、 < 演算子を operator function として渡すこともできる:

let sorted = sort(anArray, <)

後置記法

関数の最後の引数に渡すクロージャは、関数呼び出しの後ろに置くことができる(Ruby と同じ):

let doubled = map([1, 2, 3], { $0 * 2 })
// ↓
let doubled = map([1, 2, 3]) { $0 * 2 }

@autoclosure

@autoclosure 属性を持つ引数に渡される式は、評価されずにクロージャとしてキャプチャされる:

func doTwice(f: @autoclosure () -> Void) {
    f()
    f()
}

doTwice(print("hello")) // => hellohello

面白いが使いどころが思いつかない。明示的にクロージャを書けばいいと思うんだが。短絡評価する演算子を定義するとき使えるとのこと

キャプチャリスト

クロージャが外部の変数をどうキャプチャするか指定できる。 Objective-C で面倒だった self の循環参照回避が簡単になる:

// self がクロージャを強参照し、クロージャが self を強参照して循環参照に陥る
self.aProperty = {
    self.doSomething()
}

// unowned self としてキャプチャすると、クロージャは self を所有しない
self.aProperty = {
    [unowned self] in
    self.doSomething()
}