swift-閉パッケージ

6311 ワード

閉パケットは、コードに伝達され、使用されるコードブロックからなる.Swiftの閉パッケージは、CおよびObjective-Cのブロック(blocks)および他の言語の匿名関数のいくつかと似ています.
クローズド・パッケージは、コンテキスト内の任意の定数および変数の参照をキャプチャおよび格納します.これは、クローズド・パッケージと呼ばれる定数および変数、いわゆるクローズド・パッケージです.Swiftは、キャプチャ中に関連するすべてのメモリ・アクションを管理します.
グローバル関数とネスト関数は実際には特殊な閉パッケージであり、クローズド・パッケージは次の3つの形式の1つです.•グローバル関数は、名前が付いていても値が取得されないクローズド・パッケージです.•ネストされた関数は、名前があり、クローズド・関数ドメイン内の値をキャプチャできるクローズド・パッケージです.クローズド・パッケージ式は、軽量レベルの構文で書かれたコンテキスト内の変数または定数値をキャプチャできる匿名のクローズド・パッケージです.
Swiftの閉パケット式は簡潔なスタイルを持ち、一般的なシーンでの構文最適化を奨励している.主に最適化されているのは、•コンテキスト推定パラメータと戻り値タイプを利用する•暗黙的に単一式を返す閉パケットである.すなわち、単一式閉パケットはreturnキーワード•パラメータ名の略語•後続(Trailing)閉パケット構文を省略できる
クローズドパッケージ式の構文
クローズドパッケージ式の構文には、次のような一般的な形式があります.
{ (parameters) -> returnType in
    statements
}

閉パッケージ式構文では、定数、変数、inoutタイプをパラメータとして使用できます.デフォルト値は指定できません.パラメータリストの最後に可変パラメータを使用することもできます.メタグループは、パラメータと戻り値としても使用できます.次の例では、関数の代わりに閉パッケージを使用します.
reversed = name.sort({ s1: String, s2: String -> Bool in
  return s1 > s2
})

インラインクローズ式(以上のように)関数と戻り値タイプは、括弧の外ではなく括弧内に書かれている.閉パッケージの関数体部分はキーワードinによって導入されている.このキーワードは、閉パッケージのパラメータと戻り値タイプが完了し、閉パッケージの関数体が展開しようとしていることを示している.この閉パッケージの関数体は非常に短いため、1行に書くことができる.reversed = name.sort({ s1: String, s2: String -> Bool in return s1 > s2 })コンテキストに基づいてタイプを推定
ソート閉包関数はsort(_:)メソッドのパラメータとして伝達されるので、Swiftはそのパラメータと戻り値のタイプを推定することができる.sort(_:)メソッドは文字列配列によって呼び出されるため、そのパラメータは(String, String) -> Boolタイプの関数でなければならない.これは、(String, String)およびBoolのタイプが閉包式の定義の一部として必要でないことを意味する.すべてのタイプが正確に推定できるので、戻り矢印( -> )とパラメータの周囲を囲む括弧も省略することができる:reversed = name.sort({ s1, s2 in return s1 > s2 })実際にはいずれの場合も,関数やメソッドにパラメータとしてインライン閉パケット式で構成された閉パケットが渡されると,閉パケットのパラメータと戻り値タイプを推定することができる.これは、関数またはメソッドのパラメータとしてパッケージを閉じる場合、完全なフォーマットでインラインパッケージを構築する必要はほとんどありません.
シングルエクスプレッションクローズドパッケージ暗黙的な戻り
1行式閉パケットは、returnのキーワードを省略することによって、1行式の結果を暗黙的に返すことができる.
この例では、reversed = name.sort({ s1, s2 in s1 > s2 })メソッドの2番目のパラメータ関数タイプは、閉パケットがsort(_:)タイプの値を返さなければならないことを明確にしている.閉包関数体は、Boolのタイプの値を返す単一の式( s1 > s2 )のみを含むため、ここでは曖昧ではなく、Boolのキーワードは省略することができる.
パラメータ名の略語
Swiftは自動的にインライン閉パケット式にパラメータ名の略語機能を提供し、return$0$1$2を直接使用して閉パケットのパラメータを順番に呼び出すことができる.
閉パッケージ式でパラメータ名の略語を使用する場合は、閉パッケージパラメータリストで定義を省略し、対応するパラメータ名の略語のタイプを関数タイプで推定できます.inキーワードも同様に省略することができる.なぜなら、この場合、閉包式は完全に閉包関数体から構成される:reversed = name.sort({ $0 > $1 })この例では、$0および$1は閉包中の第1および第2のStringタイプのパラメータを表す.
演算子関数
実際には、上記の例の閉パッケージ式を書く方法もあります.SwiftのStringタイプは、2つの>タイプのパラメータを1つの関数として受け入れ、Stringタイプの値を返す、番号(Bool)より大きい文字列実装を定義する.これはsort(_:)法の第2のパラメータに必要な関数タイプとちょうど一致する.したがって、より大きい番号を簡単に渡すことができます.Swiftは、より大きい番号を使用する文字列関数の実装を自動的に推定することができます.reversed = name.sort( > )テイルバック
長い閉パケットを最後のパラメータとして関数に渡す必要がある場合は、後続の閉パケットを使用して関数の可読性を向上させることができます.後続の閉パケットは、最後のパラメータとして呼び出すことをサポートする関数体カッコの後に書かれた閉パケット式です.
func someFunctionThatTakesAClosure(closure: () -> void) {
  //      
}
someFunctionThatTakesAClosure({
  //       
})
someFunctionThatTakesAClosure() {
  //       
}

以前の関数は、reversed = name.sort() { $0 > $1 }と書くことができるので、関数が閉パケット式のパラメータを1つだけ必要とする場合、後続の閉パケットを使用する場合、削除することもできます():reversed = name.sort { $0 > $1 }次に、後続の閉パッケージを使用する例を示します.
let digitNames = [
    0: "Zero", 1: "One", 2: "Two", 3: "Three", 4: "Four", 
    5: "Five", 6: "Six", 7: "Seven", 8: "Eight", 9: "Nine"
]
let numbers = [16, 58, 510]

let strings = numbers.map {
    (var number) -> String in
    var output = ""
    while number > 0 {
          output =digitNames[number % 10]! + output
          numbers /= 10
    }
    return output
}
// strings              ,  [String]
//     ["OneSix", "FiveEight", "FiveOneZero"]

ディクショナリdigitNamesの下付きラベルには、キーが存在しない場合に検索に失敗することを示すオプション値(optional value)が返されるため、感嘆符(!)が付いています.上記の例では、numbers % 10が常にdigitNames辞書の有効な下付き文字を決定することができるので、感嘆符は、下付き文字の任意のタイプの戻り値に格納されたStringタイプの値を強制的に解くために使用することができる.
取得値
閉パケットは、定義されたコンテキストで定数または変数を取得できます.これらの定数または変数を定義する元の役割ドメインが存在しなくても、閉パケットは閉パケット関数内でこれらの値を参照および変更できます.
Swiftでは,値をキャプチャできる閉パケットの最も単純な形式はネスト関数,すなわち他の関数体内に定義された関数である.ネストされた関数は、外部関数のすべてのパラメータと定義された定数と変数をキャプチャします.ネスト関数についてはswift-関数を表示できます.
閉パッケージは参照タイプです
関数または閉パッケージを定数または変数に割り当てても、実際には定数または変数の値を対応する関数または閉パッケージの参照に設定します.
非脱出閉鎖
閉包がパラメータとして関数に伝達されるが,この閉包は関数が戻った後に実行され,この閉包は関数から逃れると呼ぶ.パラメータとして閉パケットを受け入れる関数を定義すると、パラメータ名の前に@noescapeとマークして、この閉パケットがこの関数から「脱出」できないことを示すことができます.閉包寸法@noescapeは、コンパイラにこの閉包のライフサイクルを知らせることができ(翻訳者注:閉包は関数体でのみ実行され、関数体から離れて実行できないため、コンパイラは実行時のコンテキストを明確に知っている)、比較的急進的な最適化を行うことができる.
閉パケットを関数から「脱出」させる方法の1つは、この閉パケットを関数の外部で定義された変数に保存することである.例えば、非同期動作を開始する多くの関数は、completion handlerとして閉パケットパラメータを受け入れる.このような関数は、非同期操作が開始されるとすぐに返されますが、非同期操作が終了するまでパケットを閉じます.この場合、閉パケットは、関数が返された後に呼び出される必要があるため、「脱出」関数を必要とする.例:
var completionHandlers: [() -> Void] = []
func someFunctionWithEscapingClosure(completionHandler: () -> Void) {
       completionHandlers.append(completionHandler)
}
someFunctionWithEscapingClosure(_:)関数は、関数外で定義された配列に追加された閉パケットをパラメータとして受け入れる.このパラメータを@noescapeと表記しようとすると、コンパイルエラーが表示されます.
オートクローズド
自動閉パッケージは、パラメータとして関数に渡される式をパッケージするために自動的に作成される閉パッケージです.この閉パケットはパラメータを受け入れず、呼び出されるとパッケージされた式の値が返されます.この便利な構文では、明示的な閉パケットの代わりに一般的な式を使用することができ、閉パケットのカッコを省略することができます.
パラメータとして閉パケットを受け入れる関数を呼び出すことが多いが,そのような関数を実現することは少ない.一例として、assert(condition:message:file:line:)関数は、そのconditionパラメータおよびmessageパラメータとして閉パケットを受け入れる.そのconditionパラメータはdebugモードでのみ評価され、そのmessageパラメータはconditionパラメータがfalseである場合にのみ計算される.
自動閉パケットは、この閉パケットを呼び出すまでコードセグメントが実行されないため、評価を遅らせることができます.遅延評価は、コードがいつ実行されるかを制御できるため、副作用(Side Effect)とコストの高いコードにとって有益です.