Functions and Closures
Xcode 6.0 Beta
Swift学習中。
The Swift Programming Language.epubのA Swift Tour内のFunctions and Closuresの項を読んだ。
関数の定義方法
キーワード func の後ろにスペースで区切って関数名をつける。括弧 ( ) 内に引数のリストを記述する*1。関数の戻り値は、引数リストの ( ) の後ろに続けて、「 -> 戻り値型」を記述する。
func greet(name: String, day: String) -> String { return "Hello \(name), today is \(day)." } let greeting = greet("Bob", "Tuesday")
タプル
タプルを使って、関数から複数の戻り値を返すことができる。
func getGasPrices() -> (Double, Double, Double) { return (3.59, 3.69, 3.79) } let prices = getGasPrices() println(prices.0) //=>3.59 println(prices.1) //=>3.69 println(prices.2) //=>3.79
可変長引数
可変長引数を受け取るには、関数宣言の引数で「 ... 」を指定する。可変長引数は配列として受け取る。
func sumOf(numbers: Int...) -> Int { var sum = 0 for number in numbers { sum += number } return sum; } println(sumOf()) //=>0 println(sumOf(42, 597, 12)) //=>651
クロージャ
関数はネストさせることができる。ネストされた関数は、外側の関数内で宣言された変数にアクセスすることができる。
func returnFifteen() -> Int { var y = 10 func add() { y += 5 } add() return y } println(returnFifteen()) //=>15
関数は第一級オブジェクトであり、高階関数として扱える。
以下は、戻り値として関数を返す例。
func makeIncrementer() -> (Int -> Int) { func addOne(number: Int) -> Int { return 1 + number } return addOne } let increment = makeIncrementer() // incrementは(Int->Int)型の関数オブジェクト println(increment(7)) //=>8
以下は、引数として関数を受け取る例。
func hasAnyMatches(list: Int[], condition: Int -> Bool) -> Bool { for item in list { if condition(item) { return true } } return false } func lessThanTen(number: Int) -> Bool { return number < 10 } var numbers = [20, 19, 7, 12] hasAnyMatches(numbers, lessThanTen) // true
クロージャは無名で生成することができる。その場合の書式は、
{
(引数名: 引数型) -> 戻り値型 in
// 以下実行コード
}
のようにして、in で型定義とコードボディを区切る。
例:
numbers.map({ (number: Int) -> Int in let result = 3 * number return result })
クロージャの型が推論可能な状況であれば、引数の型、戻り値の型宣言は省略できる。
numbers.map({ number in 3 * number })
引数を名前の代わりに「$番号」で参照することもできる。また、ある関数の最後の引数がクロージャであり、それが引数リストの最後である場合、関数呼び出しの括弧 ( ) の直後にクロージャのボディ部を記述することができる。
let array = [3, 2, 5, 1, 4] sort(array) {$0 < $1} // sort(array: T[], pred: (T, T) -> Bool) の関数呼び出しだが、左のように書ける for n in array { println(n) //=>1, 2, 3, 4, 5 }
薄々感づいていたが、はっきりわかった。
この言語Rubyのパクリだ!
まあ、そうだとしても、わしは一向に構わんよ。
では、今日はここまで。
*1:ここでは紹介されていないが、引数にラベルをつけることもでき、それには func functionName(label1 name1: String, label2 name2 : Int) のような形式で定義し、functionName(label1: "", label2: 0) のようにして呼び出す。