[Swift] クロージャーの色々な書き方に慣れる
Swiftのクロージャー(Closures)は、書き方が独特でなかなか最初はとっつきづらいところ。今日はクロージャーの色々な書き方をブログに書きました。コードを真似して書いてみれば、きっとクロージャーに慣れると思うので、使ってみてください。
https://swift.sandbox.bluemix.net/#/repl/5a0255b1d0f9bc44a212103e
また、クロージャーについての公式ドキュメントは以下にあります。
https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Closures.html
それぞれ適宜ご利用ください。
今回は、以下の配列を逆順にソートする処理を、クロージャーを用いて実装したいと思います。
これについて、以降ではクロージャーで実現したいと思います。
そしてSwiftのクロージャーは、この基本形を色々な形で省略することができます(その辺が初心者には難しいところ)。1つずつ見て行きたいと思います。
さらに、関数の引数にクロージャーが1つのみ定義されている場合には、
本ブログでは、Swift、Go言語、Python、フロントエンド、Linux、Node.js、インフラ、Java、機械学習、などの技術トピックを発信をしていきます。「プログラミングで困ったその時に、解決の糸口を見つけられる」そんな目標でブログを書き続けています。今後も役立つネタを書いていきますので、ぜひ本ブログのRSSやTwitterをフォローして貰えたら嬉しいです ^ ^
最後までご覧頂きましてありがとうございました!
目次
サンプルコードとリファレンス
このブログで記載しているコードは、以下のオンラインデモで動くようにしています。https://swift.sandbox.bluemix.net/#/repl/5a0255b1d0f9bc44a212103e
また、クロージャーについての公式ドキュメントは以下にあります。
https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Closures.html
それぞれ適宜ご利用ください。
クロージャーの書き方
クロージャーとは処理のまとまりを表すもので、例えばJavascriptでは処理のコールバックなどでよく使われています。Swiftでもクロージャーを使うことができます。今回は、以下の配列を逆順にソートする処理を、クロージャーを用いて実装したいと思います。
let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
(クロージャーではなく)関数を渡す
クロージャーの記法を扱う前に、関数を渡して同様の処理を実現してみたいと思います。以下のように実装します。// 2要素の大小比較をする関数 func backward(_ s1: String, _ s2: String) -> Bool { return s1 > s2 } // ソート処理を引数に渡す. var reversedNames = names.sorted(by: backward) print(reversedNames) // ["Ewa", "Daniella", "Chris", "Barry", "Alex"]
sorted
のby
引数は「文字列を2つ受け取り比較結果をBoolで返す処理」を受け取るようになっていて、その形に合う関数を渡すことでソート処理を行うことができます。これについて、以降ではクロージャーで実現したいと思います。
クロージャーの基本形
まずはクロージャーの基本的な書き方です。以下のような構文として定義されています。// クロージャーの構文定義 { (parameters) -> returnValue in statements }具体的に実装すると、以下のようになります。
// クロージャーの基本記法 reversedNames = names.sorted(by: { (s1: String, s2: String) -> Bool in return s1 > s2 })これが基本的な使い方です。書き方がちょっと独特で慣れづらいですが、省略せずに書くとこのようになります。
そしてSwiftのクロージャーは、この基本形を色々な形で省略することができます(その辺が初心者には難しいところ)。1つずつ見て行きたいと思います。
1行でクロージャーを書く場合
上記のクロージャーを1行で書くこともできます。// 1行で書く. reversedNames = names.sorted(by: { (s1: String, s2: String) -> Bool in return s1 > s2 })また、1行で書く場合には、
return
を省略することも可能です。// returnを省略した reversedNames = names.sorted(by: { (s1: String, s2: String) -> Bool in s1 > s2 })この辺りの挙動は、他の言語のクロージャーと似てますね。
型定義を省略する
クロージャーは、それを代入されるところ(今回の例だとsorted
関数の引数)で、どのような形であるかがわかっているので、クロージャーから型定義(=引数の型と戻り値の定義)を省略することができます。// 引数と戻り値の型定義を省略したバージョン reversedNames = names.sorted(by: { s1, s2 in return s1 > s2 })また、1行でクロージャーを書く場合には、前述の通り
return
を省略することもできます。// returnも省略した reversedNames = names.sorted(by: { s1, s2 in s1 > s2 })だいぶシンプルになってきましたね。この辺はよく使われる形かなと思います。
ショートハンド引数名(引数名の省略)
クロージャーの中では、(シェルの引数のように)$0
や$1
などの変数で引数を参照することができます。それに合わせてクロージャー自体の引数の定義を省略することもできます。// クロージャーの引数定義を省略し、$0と$1で引数にアクセス. reversedNames = names.sorted(by: { $0 > $1 })この書き方はシンプルですが、使いやすいかどうかは人次第と思います。
トレーリングクロージャー(Trailing Closures)
関数の引数の一番最後にクロージャーが定義される場合、以下のような特別な記法で実装することができます。// トレーリングクロージャー reversedNames = names.sorted() { $0 > $1 }一旦関数を
()
で閉じて、その後にクロージャーを書く感じです。僕はSwiftを始めて最初はこの書き方の意味がわかりませんでした・・・(泣)。さらに、関数の引数にクロージャーが1つのみ定義されている場合には、
()
自体も省略することができます。reversedNames = names.sorted { $0 > $1 }とてもシンプルですが、なかなかクセの強い書き方です。トレーリングクロージャーの記法はよく使われるので、慣れて行きたいところです。
(参考)オペレータ関数の利用
今回のsorted
で文字列の並び替えをする場合、文字列で定義されている比較演算子(>
など)は、Swiftではメソッドとして実装されているため、以下のような呼び出しも可能です。reversedNames = names.sorted(by: >)Swiftの言語仕様を知らないと、これだけ見たらなんのこっちゃわかりませんが、知っておくと良いと思います。
最後に
Swiftのクロージャーについて、このブログを書くまでは頭の中が混乱していましたが、書き出してみるととってもスッキリしました。ぜひ一度手を動かして書いてみることをお勧めします。本ブログでは、Swift、Go言語、Python、フロントエンド、Linux、Node.js、インフラ、Java、機械学習、などの技術トピックを発信をしていきます。「プログラミングで困ったその時に、解決の糸口を見つけられる」そんな目標でブログを書き続けています。今後も役立つネタを書いていきますので、ぜひ本ブログのRSSやTwitterをフォローして貰えたら嬉しいです ^ ^
最後までご覧頂きましてありがとうございました!