Menu

Category

Archive

logo


The Swift Programming Language ~ Closures

2014-06-10 12:00:00 +0900
  • このエントリーをはてなブックマークに追加

iBooks にある “The Swift Programming Language” の勉強メモ。Objective-C と C を普段書いている自分から、ちょっと馴染みがないものを特にまとめておきます。目次は こちら

今回は、Closure に関して。

Closure

Closure は自己完結する機能のブロックです。 Closure は、C や Objective-C のブロック、他の言語ではラムダと似ているもの。グローバル関数とネストされた関数は、Closure の特殊なケースと考えることができます。

  • ・グーバル関数は、名前を持ち、なんの値もキャプチャしない Closure。
  • ・ネストされた関数は、名前を持ち、ネストしている関数の値をキャプチャしている Closure。
  • ・Closure は、名前のない、文脈によって値をキャプチャしている、簡潔に書かれたもの。

Sort 関数は、引数に他の関数を取る関数です。この Sort 関数を例に、Closure についての説明をしていきます。

1. Closure とは

以前 の記事のネストされた関数も、大きな関数の中の一定のコードを整理するいい方法でしたが、より簡潔に書きたい場合があると思います。そのような場合に、Closure が使えます。

Sort 関数は、引数に配列と、Closure を取ります。この Closure は同じ型の引数を 2 つ取ります。そして、どちらの値が新しく返す配列の順番の中で先に来るかを Bool 型で返します。

1
2
3
4
5
6
7
8
let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]

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

var reversed = sort(names, backwards)
// reversed is equal to ["Ewa", "Daniella", "Chris", "Barry", "Alex"]

この例では、Sort 関数の引数に関数を受け取っています。関数は、Closure の特殊なケースなので、関数を引数にすることができます。Closure を使用することで、この Sort 関数を実行するのにより効率的に、書くことができます。それを順にみていきます。

2. 基本的な Closure

まずは、コードです。

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

このコードは、先ほどの Sort 関数と全く同じ機能を持ちます。まず、{} 内の () にて、Closure の引数を指定します。そして、-> の後に返り値。in キーワードは、Closure の本体が始まるという意味です。ここでは、引数を比べて、その Bool を返すだけというシンプルなものです。これが基本的な Closure のシンタックスです。

3. Closure の型推論

この Sort Closure は、Sort 関数への引数として渡されています。したがって、Swift は、この引数の型を推論することがき、上記のコードをより簡潔に書くことができます。つまり、この Sort Closure の引数の型、返り値を省略し、下記のように書くことができます。

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

Closure を関数の引数として渡す際には、いつでも Swift の型推論に頼ることができます。なので、めったに 2 のようなコードを書く必要はありません。

4. Closure 内での return 文の省略

Sort Closrure のような 1 文で完結するような Closure では、return 文さえも省略することができます。

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

この Closure は、本体に s1> s2 という 1 文しかなく、Bool を返すということは明らかです。したがって、return 文を省略できます。

5. 引数名の省略

このような inline closure に、Swift は自動的に引数の名前を用意してくれます。それらは、$0, $1, $2… と参照することができます。つまり、これを使えば、引数名さえも省くことができます。

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

6. Operator Functions

Swift の String 型は、> オペレーターを 2 つの引数を取り、Bool を返す関数として実装しています。これを Operator Function というようです。これを利用すれば、Sort 関数をこのように書くことがきます。Operator Function は、別に解説されたページがあるようです。

1
reversed = sort(names, >)

最初の完全に定義された関数を引数にとっていた形と比べると、信じられないほど簡潔になりました。