Contents

スウィフト – クロージャー
クロージャって何?
クロージャとはただ単に変数に代入された関数であると思っていた。
ちなみにAppleのSwiftのテキストには、下記のように定義されている。
{ (parameters) -> return type in
statements
}
Swift 4のクロージャは、ブロックとして編成され、CやObjective C言語のようなどこでも呼び出される自己完結型関数のクロージャと似ています。関数内で定義された定数と変数参照は、キャプチャされ、クロージャに格納されます。関数はクロージャの特殊なケースとみなされ、次の3つの形式をとります。
グローバル関数 | 入れ子関数 | 閉じ式 |
---|---|---|
値を取得しない | 囲み関数から値を取り込む | 隣接するブロックから値を取得します。 |
- コンテキストからパラメータと戻り値の型を推論します。
- 単一式クロージャからの暗黙の戻り値。
- 引数の省略名と
- 末尾クロージャの構文
構文
以下は、パラメータを受け取り、データ型を返すクロージャを定義する一般的な構文です。
{ (parameters) −> return type in statements }
以下は簡単な例です –
let studname = { print("Welcome to Swift Closures") } studname()
私たちが上記のプログラムを遊び場で実行すると、次の結果が得られます。
Welcome to Swift Closures
次のクロージャは2つのパラメータを受け取り、Bool値を返します。
{ (Int, Int) −> Bool in Statement1 Statement 2 --- Statement n }
以下は簡単な例です –
let divide = { (val1: Int, val2: Int) -> Int in return val1 / val2 } let result = divide(200, 20) print (result)
次の結果が得られます。
10
閉鎖式
入れ子関数は、コードブロックの命名と定義の便利な方法。関数の宣言と名前の全体を表すのではなく、より短い関数を表すために使用されます。関数を明確な簡潔なステートメントで表現することは、閉包式によって実現されます。
昇順プログラム
文字列をソートすることは、スタンダードライブラリで既に利用可能なSwift 4sのキー予約関数 “sorted”によって実行されます。この関数は、指定された文字列を昇順にソートし、古い配列に記述されているサイズとデータ型が同じ新しい配列に要素を返します。古い配列は同じままです。
2つの引数がソートされた関数内で表されます。
- 既知の型の値は配列として表されます。
- 配列の内容(Int、Int)を返し、配列が適切にソートされている場合はブール値(Bool)を返します。そうでない場合はtrueを返し、そうでない場合はfalseを返します。
入力文字列を持つ通常の関数が書き出され、ソートされた関数に渡され、文字列が新しい配列にソートされます。
func ascend(s1: String, s2: String) -> Bool { return s1 > s2 } let stringcmp = ascend(s1: "Swift 4", s2: "great") print (stringcmp)
私たちが上記のプログラムを遊び場で実行すると、結果は次のようになります。
true
icecreamのためにソートされる最初の配列は、 “Swift 4″と “great”として与えられます。配列をソートする関数は、文字列データ型として宣言され、戻り値の型はBooleanと記述されています。両方の文字列が比較され、昇順にソートされ、新しい配列に格納されます。ソートが成功した場合、関数は真の値を返します。そうでなければ、偽を返します。
クロージャ式の構文では、
- 定数パラメータ、
- 可変パラメータ、および
- inoutパラメータ。
クロージャ式はデフォルト値をサポートしていませんでした。VariadicパラメータとTuplesは、パラメータ型と戻り型として使用することもできます。
let sum = { (no1: Int, no2: Int) -> Int in return no1 + no2 } let digits = sum(10, 20) print(digits)
私たちが上記のプログラムを遊び場で実行すると、次の結果が得られます。
30
関数ステートメントで言及されているパラメーターと戻り値の型宣言は、 ‘in’キーワードを使用したインライン閉包式関数でも表現できます。パラメータと戻り値の型を宣言すると、 ‘in’キーワードを使用してクロージャーの本体が示されます。
単一式の暗黙的な戻り値
ここでは、ソートされた関数の2番目の引数の関数型は、Bool値がクロージャによって返されなければならないことを明確にしています。クロージャーの本体にはBool値を返す単一の式(s1> s2)が含まれているため、あいまいさがなく、returnキーワードを省略できます。
式終了時に単一の式文を返すために、 ‘return’キーワードはその宣言部では省略されています。
var count:[Int] = [5, 10, -6, 75, 20] let descending = count.sorted(by: { n1, n2 in n1 > n2 }) let ascending = count.sorted(by: { n1, n2 in n1 < n2 }) print(descending) print(ascending)
私たちが上記のプログラムを遊び場で実行すると、次の結果が得られます。
[75, 20, 10, 5, -6] [-6, 5, 10, 20, 75]
ステートメント自体は、string1が文字列2より大きい場合はtrueを返し、そうでない場合はfalseを返すため、ここではreturnステートメントは省略されています。
既知のタイプのクロージャ
2つの数の加算を考えてみましょう。加算は整数データ型を返すことがわかります。したがって、既知の型閉包は –
let sub = { (no1: Int, no2: Int) -> Int in return no1 - no2 } let digits = sub(10, 20) print(digits)
私たちが上記のプログラムを遊び場で実行すると、次の結果が得られます。
-10
引数としての短縮名としてのClosuresの宣言
Swift 4は、インラインクロージャに自動的に簡略化された引数名を提供します。これは、クロージャの引数の値を$ 0、$ 1、$ 2などの名前で参照するために使用できます。
var shorthand: (String, String) -> String shorthand = { $1 } print(shorthand("100", "200"))
ここで、$ 0と$ 1は、クロージャの第1と第2の文字列引数を参照します。
私たちが上記のプログラムを遊び場で実行すると、次の結果が得られます。
200
Swift 4は、ユーザが$ 0、$ 1、$ 2 — $ nを表すことにより、インライン閉包を簡略な引数名として表現することを容易にします。
クロージャ式の中に簡略化された引数名を表すとき、クロージャの引数リストは定義セクションで省略されます。関数の型に基づいて、省略形の引数名が導出されます。省略形の引数は式の本文で定義されているため、 ‘in’キーワードは省略されています。
演算子関数としてのクロージャ
Swift 4は、クロージャーとしてオペレーター機能を提供するだけでメンバーにアクセスする簡単な方法を提供します。前の例では、キーワード ‘Bool’は、文字列が等しい場合は ‘true’を返し、そうでない場合は ‘false’を返します。
この式は、クロージャの演算子関数によって、
let numb = [98, -20, -30, 42, 18, 35] var sortedNumbers = numb.sorted ({ (left: Int, right: Int) -> Bool in return left < right }) let asc = numb.sorted(<) print(asc)
私たちが上記のプログラムを遊び場で実行すると、次の結果が得られます。
[-30, -20, 18, 35, 42, 98]
トレーラーとしての閉鎖
関数の最後の引数をクロージャ式に渡すことは、 ‘Trailing Closures’の助けを借りて宣言されます。それは{}でfunction()の外側に書かれています。1行に関数をインラインで書くことができない場合、その使用法が必要です。
reversed = sorted(names) { $0 > $1}
{$ 0> $ 1}は外側(名前)で宣言された末尾のクロージャとして表されます。
import Foundation var letters = ["North", "East", "West", "South"] let twoletters = letters.map({ (state: String) -> String in return state.substringToIndex(advance(state.startIndex, 2)).uppercaseString }) let stletters = letters.map() { $0.substringToIndex(advance($0.startIndex, 2)).uppercaseString } print(stletters)
私たちが上記のプログラムを遊び場で実行すると、次の結果が得られます。
[NO, EA, WE, SO]
値と参照型の取得
Swift 4では、定数と変数の値の取り込みはクロージャの助けを借りて行われます。さらに、変数がもはや存在しなくても、クロージャー本体内の定数および変数の値を参照および変更します。
定数値と変数値の取得は、他の関数の本体に関数を書くことでネストされた関数を使用することによって実現されます。
ネストされた関数のキャプチャ –
- 外部関数の引数
- Outer関数内で定義された定数と変数を取り込みます。
Swift 4では、定数または変数が関数内で宣言されると、その変数への参照もクロージャによって自動的に作成されます。また、2つ以上の変数を次のように同じクロージャーとして参照する機能も提供します。
let decrem = calcDecrement(forDecrement: 18) decrem()
ここで、oneDecrement変数とDecrement変数は、両方とも同じメモリブロックをクロージャ参照とします。
func calcDecrement(forDecrement total: Int) -> () -> Int { var overallDecrement = 100 func decrementer() -> Int { overallDecrement -= total print(overallDecrement) return overallDecrement } return decrementer } let decrem = calcDecrement(forDecrement: 18) decrem() decrem() decrem()
私たちが上記のプログラムを遊び場で実行すると、次の結果が得られます。
82 64 46
外部関数calcDecrementが呼び出されるたびに、それはdecrementer()関数を呼び出し、値を18だけデクリメントして、外部関数calcDecrementの助けを借りて結果を返します。ここでは、calcDecrementはクロージャとして機能します。
関数decrementer()には引数がありませんが、デフォルトでclosureは変数 ‘overallDecrement’と ‘total’を参照しています。指定された変数の値のコピーは、新しいdecrementer()関数とともに格納されます。Swift 4は、変数が使用されていないときにメモリスペースを割り当てたり割り当てを解除したりすることによってメモリ管理機能を処理します。