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) のようにして呼び出す。