it-swarm-ja.com

Swiftのクロージャ宣言構文が関数宣言と異なる理由

let closure = { (args) -> ReturnT in ... }

v.s。

func function(args) -> ReturnT { ... }

AppleがOccamのかみそりの原則に従い、クロージャーと関数の宣言を同じにしないのはなぜですか?たとえば、クロージャーは次のように定義できます。

let closure = (args) -> ReturnT { ... }

これは、JavaScriptや他のスクリプト言語での実装方法です。関数とクロージャは実際には同じなので、これもより合理的に見えます。そして逆に、括弧内に引数と戻り値の型を置くのは奇妙に見え、プログラマーを混乱させる可能性があります。

3
kelin

Swiftは、通常の関数の関数パラメーターにもラムダスタイルの構文を選択しました。通常の関数と閉じた関数の唯一の違いは、中括弧の位置とinキーワードの使用です。

AppleはClosuresを「渡してコードで使用できる自己完結型の機能ブロック」と説明しています。この「ブロック」スタイルの概念は、すべての例で明らかです。

たとえば、次の通常の関数:

func backwards(s1: String, _ s2: String) -> Bool {
    return s1 > s2
}

Sort関数に渡して、ソートを逆にすることができます。

var reversed = names.sort(backwards)

クロージャ形式では、次のようにコードのブロックを関数に渡します。

reversed = names.sort( { (s1: String, s2: String) -> Bool in return s1 > s2 } )

それはあまり似ていない。ただし、構文を使用すると、いくつかの最適化を行うことができます。 型推論を使用すると、

reversed = names.sort( { s1, s2 in return s1 > s2 } )

暗黙的な戻り値を使用すると、

reversed = names.sort( { s1, s2 in s1 > s2 } )

そしてShorthand Argument Namesを使用すると、

reversed = names.sort( { $0 > $1 } )

ただし、最も興味深い構文のバリエーションは「末尾クロージャー」で、括弧の外側の最後のメソッド引数にクロージャーを渡すことができます。sort関数は引数を1つだけ取ります。括弧を省略することもできます。したがって、次のようになります。

reversed = names.sort { $0 > $1 }

これは小さな違いのように思えるかもしれませんが、次の例を検討してください。

let strings = numbers.map {
    (number) -> String in
    var number = number
    var output = ""
    while number > 0 {
        output = digitNames[number % 10]! + output
        number /= 10
    }
    return output
}

これは、マップ関数で末尾クロージャを使用します。中かっこはもうそれほど厄介に見えませんか?

さらに読む
Swiftプログラミング言語:クロージャ

7
Robert Harvey