Swiftではクロージャが使えるようになり、色々と便利になった。
しかし、若干わかりにくいというのも事実だ。

そこで、今回はSwiftのクロージャについて色々と試してみることにする。 
 
アップル公式を参考に少しずつ試してみよう。

The Swift Programming Language: Closures 

この例に倣って、ソートを行ってみる。

結果はこうなる。
[strawberry, orange, grape, banana, apple]
想定通りだ。

次はいよいよクロージャの登場だ
関数で処理していた部分をクロージャに置き換えてみる。

結果は先ほどと同じなので、正しく動作しているということだ。

ここからが面白いところで、この記述を色々と省略して短くすることが出来る。
まずは引数の型と戻り値の型を省略してみる。

先ほどと同じ結果が表示される。

次にreturnを省略してみる。

これもちゃんと動作する。

さらにこのように記述することも出来る

$0は一つ目の引数、$1は2つ目の引数を表す。
こう記述すればソースがかなりスッキリしてくる。

なお、Arrayのsortedメソッドを使用しても同じことが出来る。

これを短縮するとこうなる。

だがちょっと待って欲しい。
この記述だと下記のようなエラーが出て、正常に動作しないことに気付く。
Playground execution failed: <EXPR>:13:34: error: ambiguous use of operator '>'
var reversed = fruits.sorted({$0 > $1})
^
Foundation.>:1:6: note: found this candidate
func >(lhs: String, rhs: NSString) -> Bool
^
Foundation.>:1:6: note: found this candidate
func >(lhs: NSString, rhs: String) -> Bool
^
ちなみに、以下のように比較演算子を逆にすると正しく動く

この不可解な現象について調べてみるとstackoverflowに同じような問題が見つかった。

Implicit returns from single-expression closures in swift playground - Stack Overflow

この回答での検証が興味深いので、自分でも試してみる。

この場合、一つ目の比較では問題なくtrueが表示されるが、2つ目の比較で上記のエラーが表示される。
これは実に不可解だ。
Stringの比較のうち">"を使う場合にのみエラーが起こるということになる

回答を読み進めると興味深いことを書いてある。
「Foundationのimportを消すと問題なく動く」と。
その通りにしてみたら、確かに期待通りの動きとなった。

しかし、Foundationは多くの場面で必要となるであろうから、これをimportしないのは非現実的だ。
なので、とりあえずの対応方法としては
Arrayのsorted()を使用せずにグローバルな関数のsorted()を使用する
と言ったところであろうか。

Trailing Closures
公式のドキュメントや色々なサイトを見ていると、ちょっと見慣れない書き方(というか、不可解な書き方)をチラホラと見かけることがある。
先ほどの例で言うとこのような感じだ。

「なんだこれは。クロージャが引数の外に出てしまっているじゃないか。これじゃエラーが出るだろう」
私は最初そう思った。
しかし、これを実際にPlaygroundに打ち込むとエラーにならないのだ。

これはTrailing Closuresというもので
引数の最後がクロージャの場合は、()の外に出してしまってもいい
らしい。

別の例としてArrayのmap()を使う場合を見てみよう。

map()は引数でクロージャを渡すだけなので、引数自体は空になり、クロージャ本体は外に記述するので、このようになる。

さらに、引数が空になる場合、()を省略することが出来るので

という記述方法も可能だ。

同じ意味でも記述方法が色々あるので、ドキュメントやサイトで調べ物をする際は、これらのことを頭の隅に置いておくようにしたい。