Swift
swift4

SwiftTourをさっと読む ~Functions and Closures ~

SwiftTourをさっと読む ~ Functions and Closures ~

さてさて、少し間が空いてしまいましたが、
Simple Values
Control Flow
に続いて、Functions and Closures。
関数とクロージャ。難しそうですね。
さっと見ていきます。

バージョンは4.2です

※個人的に学んだことを書き足してます。

関数

宣言方法

宣言方法
func 関数名(引数の名前:引数の型, 引数の名前:引数の型) -> 戻り値の型 {
  ・・・処理・・・
  return 戻り値
}

-> 戻り値の型を書かなければ戻り値のない関数となる。

サンプル

サンプル
func greet(person: String, day: String) -> String {
    return "Hello \(person), today is \(day)."
}
greet(person: "Bob", day: "Tuesday") // "Hello Bob, today is Tuesday."

関数を利用する際は引数ラベルを書く必要がある。
(上記の例で言えば、person: "Bob"の部分)

ただし、_を使うことでラベルの記述を省略できる

ラベルの省略
func greet(_ person: String, _ day: String) -> String {
    return "Hello \(person), today is \(day)."
}
greet("Bob", "Tuesday") // "Hello Bob, today is Tuesday."

外部引数ラベル(外部引数名/名前付き引数)

(どの呼び方が一般的なのでしょうか)

関数を呼び出す際のラベルを引数ラベルとは別に設定することができる

外部引数ラベル
func talk(with person: String) -> String {
    return "Hi \(person). How are you?"
}
talk(with:"Bob") // "Hi Bob. How are you?"

(個人的にはこれすごく好き。)

戻り値にタプルを用いる

戻り値にタプルを用いる
func calculateStatistics(scores: [Int]) -> (min: Int, max: Int, sum: Int) {
    var min = scores[0]
    var max = scores[0]
    var sum = 0

    for score in scores {
        if score > max {
            max = score
        } else if score < min {
            min = score
        }
        sum += score
    }

    return (min, max, sum)
}
let statistics = calculateStatistics(scores: [5, 3, 100, 3, 9])
print(statistics.sum) // 120
print(statistics.2)   // 120

タプルで戻ってきた値は名前、もしくは数字でアクセスすることができる。

関数のネスト

関数のネスト
func returnFifteen() -> Int {
    var y = 10
    func add() {
        y += 5
    }
    add()
    return y
}
returnFifteen()

関数はネストさせることができる。
内部の関数は外部の関数で宣言された変数にアクセスすることができる。

関数は第一級クラス

Functions are a first-class type. This means that a function can return another function as its value.

関数は第一級クラスなので、関数は戻り値や引数に他の関数を利用できる。

戻り値に関数

戻り値に関数
func makeIncrementer() -> ((Int) -> Int) {
    func addOne(number: Int) -> Int {
        return 1 + number
    }
    return addOne
}
var increment = makeIncrementer()
increment(7)

引数に関数

引数に関数
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(list: numbers, condition: lessThanTen)

クロージャ

クロージャとは、あとで呼び出すことのできるコードのかたまり。クロージャが作成されたスコープ内で利用できる変数や関数にアクセスすることが可能。

基本形

クロージャ
numbers.map({ (number: Int) -> Int in
    let result = 3 * number
    return result
})

{}を使うことで無名関数が使える。
inを使用して、引数と戻り値の型を処理から分離すること。

省略

クロージャの引数の型と戻り値の型の省略
let mappedNumbers = numbers.map({ number in 3 * number })
print(mappedNumbers)

引数の型や戻り値の型が明白な場合は省略が可能。

パラメータへのアクセス

パラメータへのアクセス
let sortedNumbers = numbers.sorted { $0 > $1 }
print(sortedNumbers)

クロージャのパラメータへは名前ではなく$数字でアクセスすることができる。とても短いクロージャでは特に有効。

おわり

関数やクロージャとか聞くと、難しそうだと身構えてしまいますが、
使っていくうちにハラオチしていきますね。
何か間違いがあればご指摘お願い致します。
(日本語表記の誤り/揺れがこわい)

おしまい。