Closures クロージャ

Closures are self-contained blocks of functionality that can be passed around and used in your code. Closures in Swift are similar to blocks in C and Objective-C and to lambdas in other programming languages. クロージャは、機能性の完全独立のブロック、かたまりです、それは、あなたのコードにおいてあちこちに渡され使われることができます。スウィフトにおけるクロージャは、CとObjective-Cでのブロックに、そして他のプログラミング言語でのラムダ(lambda)に似ています。

Closures can capture and store references to any constants and variables from the context in which they’re defined. This is known as closing over those constants and variables. Swift handles all of the memory management of capturing for you. クロージャは、それが定義されている前後関係からのあらゆる定数や変数への参照を捕獲して、格納することができます。これは、そのような定数や変数をすっかりクローズする(閉じ込める)こととして知られています。スウィフトは、キャプチャ(その瞬間の保存)の記憶管理の全てを、あなたのために取り扱います。

Note 注意

Don’t worry if you aren’t familiar with the concept of capturing. It’s explained in detail below in Capturing Values. あなたがキャプチャの概念に馴染みがなくても、心配いりません。それは、下で詳細に値を捕獲する(キャプチャする)の中で説明されます。

Global and nested functions, as introduced in Functions, are actually special cases of closures. Closures take one of three forms: 関数で紹介される、グローバルおよび入れ子にされた関数は、実際にはクロージャの特別な場合です。クロージャは、3つの書式のうちの1つをとります:

  • Global functions are closures that have a name and don’t capture any values. グローバルな関数は、名前を持ち、まったく値をキャプチャしない(捕獲しない)クロージャです。
  • Nested functions are closures that have a name and can capture values from their enclosing function. 入れ子にされた関数は、名前を持ち、それを囲んでいる関数から値を捕獲することができるクロージャです。
  • Closure expressions are unnamed closures written in a lightweight syntax that can capture values from their surrounding context. クロージャ式は、それの周囲の前後関係から値を捕獲することができる軽快な構文で書かれる無名のクロージャです。

Swift’s closure expressions have a clean, clear style, with optimizations that encourage brief, clutter-free syntax in common scenarios. These optimizations include: スウィフトのクロージャ式は、最適化された、きれいな、明白なスタイルを持ちます、それは、通常さまざまに予想される状況において、簡潔な、混乱のない構文を助長します。これらの最適化は、以下を含みます:

  • Inferring parameter and return value types from context 前後関係からパラメータおよび戻り値の型を推論する
  • Implicit returns from single-expression closures 単一式のクロージャからの値を暗黙的に返す
  • Shorthand argument names 短縮形引数名
  • Trailing closure syntax 後付クロージャ構文

Closure Expressions さまざまなクロージャ式

Nested functions, as introduced in Nested Functions, are a convenient means of naming and defining self-contained blocks of code as part of a larger function. However, it’s sometimes useful to write shorter versions of function-like constructs without a full declaration and name. This is particularly true when you work with functions or methods that take functions as one or more of their arguments. 入れ子にされた関数は、入れ子にされた関数の中で紹介されるように、より大きい関数の一部として、いろいろな完全独立のコードの塊を名前をつけて定義する便利な手段です。しかし、まるまる完全な宣言や名前なしに、関数のような構造物のより短いものをいろいろと書くことは、時々役に立ちます。1つ以上のそれの引数として関数をとる関数またはメソッドをあなたが扱うとき、これは特に当てはまります。

Closure expressions are a way to write inline closures in a brief, focused syntax. Closure expressions provide several syntax optimizations for writing closures in a shortened form without loss of clarity or intent. The closure expression examples below illustrate these optimizations by refining a single example of the sorted(by:) method over several iterations, each of which expresses the same functionality in a more succinct way. クロージャ式は、簡潔な、焦点のあった構文で、処理の流れに組み込まれた(行内の、インラインの)クロージャを書く方法です。クロージャ式は、いくつかの構文最適化を、ある省略形式で明快さや意図の損失なしでクロージャを書くために提供します。以下のクロージャ式の例は、これらの最適化を1つの例のsorted(by:)メソッドの改良をいくどか繰り返していくことで解説します、そして、そのそれぞれは同じ機能性をより簡潔な方法で表わします。

The Sorted Method 分類メソッド

Swift’s standard library provides a method called sorted(by:), which sorts an array of values of a known type, based on the output of a sorting closure that you provide. Once it completes the sorting process, the sorted(by:) method returns a new array of the same type and size as the old one, with its elements in the correct sorted order. The original array isn’t modified by the sorted(by:) method. スウィフトの標準ライブラリはsorted(by:)と呼ばれるメソッドを提供します、それは、ある既知の型の値からなる配列の分類を、あなたが提供するあるソート(分類)を行うクロージャの出力に基づき行います。一旦それがソート処理を完了するならば、sorted(by:)メソッドは、古いものと同じ型と大きさの新しい配列を返します、そしてその要素は正しく分類された順序を持ちます。元の配列は、sorted(by:)メソッドによって修正されません。

The closure expression examples below use the sorted(by:) method to sort an array of String values in reverse alphabetical order. Here’s the initial array to be sorted: 下のクロージャ式の例は、sorted(by:)メソッドを使用してString値からなる配列を逆アルファベット順に分類します。分類される最初の配列は、ここにあります:

  1. let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]

The sorted(by:) method accepts a closure that takes two arguments of the same type as the array’s contents, and returns a Bool value to say whether the first value should appear before or after the second value once the values are sorted. The sorting closure needs to return true if the first value should appear before the second value, and false otherwise. sorted(by:)メソッドは、配列の内容物と同じ型の2つの引数をとり、そしてひとたび値が分類されるならば最初の値が第2の値の前か後のどちらに現れなければならないのかを伝えるBool値を返すクロージャを受け取ります。このソートを行うクロージャは、最初の値が第2の値の前に現れるべきならばtrueを、そうでないならばfalseを返す必要があります。

This example is sorting an array of String values, and so the sorting closure needs to be a function of type (String, String) -> Bool. この例はString値の配列を分類しています、なのでソート・クロージャは型(String, String) -> Boolの関数である必要があります。

One way to provide the sorting closure is to write a normal function of the correct type, and to pass it in as an argument to the sorted(by:) method: ソート・クロージャを提供する1つの方法は、通常の関数を正しい型で記述することです、そしてそれを1つの引数としてsorted(by:)メソッドに渡すことになります:

  1. func backward(_ s1: String, _ s2: String) -> Bool {
  2. return s1 > s2
  3. }
  4. var reversedNames = names.sorted(by: backward)
  5. // reversedNames is equal to ["Ewa", "Daniella", "Chris", "Barry", "Alex"](reversedNamesは["Ewa", "Daniella", "Chris", "Barry", "Alex"]に等しい)

If the first string (s1) is greater than the second string (s2), the backward(_:_:) function will return true, indicating that s1 should appear before s2 in the sorted array. For characters in strings, “greater than” means “appears later in the alphabet than”. This means that the letter "B" is “greater than” the letter "A", and the string "Tom" is greater than the string "Tim". This gives a reverse alphabetical sort, with "Barry" being placed before "Alex", and so on. 最初の文字列(s1)が第二の文字列(s2)より大きいならば、backward(_:_:)関数は、ソートされた配列においてs1s2の前に現れなければならないことを示す、trueを返します。文字列の中の文字のために、「より大きい」は「アルファベットにおいてより後に現れる」ことを意味します。これは文字"B"は文字"A"「より大きい」こと、そして文字列"Tom"は文字列"Tim"よりも大きいことを意味します。これは、"Barry""Alex"の前に置かれるなどの、逆アルファベット順の分類を提供します。

However, this is a rather long-winded way to write what is essentially a single-expression function (a > b). In this example, it would be preferable to write the sorting closure inline, using closure expression syntax. しかし、これは本質的に単一式の関数(a > b)であるものを書くには、相当に長たらしい方法です。この例では、クロージャ式構文を使って、ソート・クロージャを行内に書くことがずっと好ましいです。

Closure Expression Syntax クロージャ式構文

Closure expression syntax has the following general form: クロージャ式構文は、以下の一般的な形式を持ちます:

  1. { (parameters) -> return type in
  2. statements
  3. }

The parameters in closure expression syntax can be in-out parameters, but they can’t have a default value. Variadic parameters can be used if you name the variadic parameter. Tuples can also be used as parameter types and return types. クロージャ式構文中のparametersはin-outパラメータであることができます、しかしそれらは省略時の値を持つことはできません。あなたが可変長パラメータに名前をつけるならば、可変長パラメータが使われることができます。タプルもまた、パラメータ型および戻り型として使われることができます。

The example below shows a closure expression version of the backward(_:_:) function from above: 下記の例は、上のbackward(_:_:)関数のクロージャ式版を示します:

  1. reversedNames = names.sorted(by: { (s1: String, s2: String) -> Bool in
  2. return s1 > s2
  3. })

Note that the declaration of parameters and return type for this inline closure is identical to the declaration from the backward(_:_:) function. In both cases, it’s written as (s1: String, s2: String) -> Bool. However, for the inline closure expression, the parameters and return type are written inside the curly braces, not outside of them. 行内クロージャのためのパラメータと戻り型の宣言が、backward(_:_:)関数の宣言と同一であることに注意してください。両方の場合において、それは(s1: String, s2: String) -> Boolのように書かれます。しかし、行内クロージャ式のために、パラメータと戻り型は、波括弧の内側に書かれます、その外側ではなく。

The start of the closure’s body is introduced by the in keyword. This keyword indicates that the definition of the closure’s parameters and return type has finished, and the body of the closure is about to begin. クロージャのもつ本文の始まりは、inキーワードで紹介されます。このキーワードはクロージャのパラメータと戻り型の定義が終わったことを示します、そして、クロージャの本文はまさに開始しようとしています。

Because the body of the closure is so short, it can even be written on a single line: クロージャの本文がたいへん短いので、それは1つの行に書かれさえすることができます:

  1. reversedNames = names.sorted(by: { (s1: String, s2: String) -> Bool in return s1 > s2 } )

This illustrates that the overall call to the sorted(by:) method has remained the same. A pair of parentheses still wrap the entire argument for the method. However, that argument is now an inline closure. これは、sorted(by:)メソッドへの呼び出し全体が、同じもののままだったことを図解します。一対の丸括弧は、依然としてこのメソッドに対する引数をすべて包みます。しかしながら、この引数は今では1つの行内クロージャです。

Inferring Type From Context 文脈から型を推論する

Because the sorting closure is passed as an argument to a method, Swift can infer the types of its parameters and the type of the value it returns. The sorted(by:) method is being called on an array of strings, so its argument must be a function of type (String, String) -> Bool. This means that the (String, String) and Bool types don’t need to be written as part of the closure expression’s definition. Because all of the types can be inferred, the return arrow (->) and the parentheses around the names of the parameters can also be omitted: ソート(分類)するクロージャが引数としてメソッドに渡されるので、スウィフトは、それのパラメータの型とそれが返す値の型を推論することができます。このsorted(by:)メソッドは文字列の配列上で呼ばれています、それでそれの引数は型(String, String) -> Boolの関数でなければなりません。これは、(String, String)およびBool型が、クロージャ式の定義の一部として書かれる必要がないことを意味します。型の全てが推論されることができるので、戻り矢印(->)と、パラメータの名前のまわりの丸括弧もまた省略することができます:

  1. reversedNames = names.sorted(by: { s1, s2 in return s1 > s2 } )

It’s always possible to infer the parameter types and return type when passing a closure to a function or method as an inline closure expression. As a result, you never need to write an inline closure in its fullest form when the closure is used as a function or method argument. クロージャを関数やメソッドに行内クロージャ式として渡すとき、パラメータ型と戻り型を推論することは常に可能です。その結果、あなたは、行内クロージャをその最も完全な形式で書くことは、そのクロージャが関数やメソッドの引数として使われる時にまったく必要ありません。

Nonetheless, you can still make the types explicit if you wish, and doing so is encouraged if it avoids ambiguity for readers of your code. In the case of the sorted(by:) method, the purpose of the closure is clear from the fact that sorting is taking place, and it’s safe for a reader to assume that the closure is likely to be working with String values, because it’s assisting with the sorting of an array of strings. それでもなお、あなたが望むならば、依然としてあなたは型を明確にすることができます、そして、それがあなたのコードの読者のために曖昧さを避けるならば、そうすることは推奨されます。sorted(by:)メソッドの場合、クロージャの目的はソートが行われているという事実から明快です、そして、読者がクロージャはString値を扱っているようだと仮定しても差し支えありません、なぜならそれがいくつかの文字列からなる配列のソートを手伝っているからです。

Implicit Returns from Single-Expression Closures 単一式のクロージャからの値を暗黙的に返す

Single-expression closures can implicitly return the result of their single expression by omitting the return keyword from their declaration, as in this version of the previous example: 単一の式のクロージャは、前の例のこの改作のように、returnキーワードをそれらの宣言から省略することによって、暗黙的にそれのただ1つの式の結果を返すことができます:

  1. reversedNames = names.sorted(by: { s1, s2 in s1 > s2 } )

Here, the function type of the sorted(by:) method’s argument makes it clear that a Bool value must be returned by the closure. Because the closure’s body contains a single expression (s1 > s2) that returns a Bool value, there’s no ambiguity, and the return keyword can be omitted. ここでは、sorted(by:)メソッドの引数である関数型は、Bool値がクロージャによって返されなければならないことを明白にします。クロージャの本文がある単一の式(s1 > s2)でBool値を返すものを含むので、曖昧さはありません、それでreturnキーワードは省略されることができます。

Shorthand Argument Names 短縮形引数名

Swift automatically provides shorthand argument names to inline closures, which can be used to refer to the values of the closure’s arguments by the names $0, $1, $2, and so on. スウィフトは行内クロージャに自動的に短縮形引数名を提供します、そしてそれは、名前$0$1$2、などにでクロージャの引数の値に言及するために使われることができます。

If you use these shorthand argument names within your closure expression, you can omit the closure’s argument list from its definition. The type of the shorthand argument names is inferred from the expected function type, and the highest numbered shorthand argument you use determines the number of arguments that the closure takes. The in keyword can also be omitted, because the closure expression is made up entirely of its body: あなたがこれらの短縮形引数名をあなたのクロージャ式の中で使用するならば、あなたはクロージャの引数リストをその定義から省略することができます。短縮形引数名の型は、期待される関数型から推論されます、そしてあなたが使用する最も高い番号のついた短縮形引数は、クロージャがとる引数の数を決定します。inキーワードもまた、クロージャ式がもっぱらその本文から成り立つので、省略されることができます:

  1. reversedNames = names.sorted(by: { $0 > $1 } )

Here, $0 and $1 refer to the closure’s first and second String arguments. Because $1 is the shorthand argument with highest number, the closure is understood to take two arguments. Because the sorted(by:) function here expects a closure whose arguments are both strings, the shorthand arguments $0 and $1 are both of type String. ここでは、$0$1は、クロージャの1番目と2番目のString引数に言及します。$1は最も高い数をもつ略記引数であることから、クロージャは2つの引数を取ると理解されます。sorted(by:)関数はここではそれの引数が両方とも文字列であるクロージャを期待することから、略記引数$0$1は両方とも型Stringのものです。

Operator Methods 演算子メソッド

There’s actually an even shorter way to write the closure expression above. Swift’s String type defines its string-specific implementation of the greater-than operator (>) as a method that has two parameters of type String, and returns a value of type Bool. This exactly matches the method type needed by the sorted(by:) method. Therefore, you can simply pass in the greater-than operator, and Swift will infer that you want to use its string-specific implementation: さらにより短い方法が上のクロージャ式を書くために実際にあります。スウィフトのString型は、それの文字列特有の実装の「大なり」演算子(>)をメソッドとして定義します、それは型Stringの2つのパラメータを持ち、型Boolの値を返します。これは、sorted(by:)メソッドによって必要とされるメソッド型に正確に適合します。したがって、あなたはただ単に「大なり」演算子を渡すことができます、そしてスウィフトはあなたがその文字列特有の実装を使いたいのだと推測します:

  1. reversedNames = names.sorted(by: >)

For more about operator methods, see Operator Methods. 演算子メソッドについてさらに、演算子メソッドを見てください。

Trailing Closures 後付クロージャ

If you need to pass a closure expression to a function as the function’s final argument and the closure expression is long, it can be useful to write it as a trailing closure instead. You write a trailing closure after the function call’s parentheses, even though the trailing closure is still an argument to the function. When you use the trailing closure syntax, you don’t write the argument label for the first closure as part of the function call. A function call can include multiple trailing closures; however, the first few examples below use a single trailing closure. あなたが関数の最後の引数としてクロージャ式を関数に渡す必要がある、そしてそのクロージャ式が長いならば、代わりに後付クロージャとしてそれを書くことは役に立つことがありえます。あなたは、後付クロージャを関数呼び出しのもつ丸括弧それらの後に書きます、そうであってもその後付クロージャは依然として関数への引数のままです。あなたが後付クロージャ構文を使うとき、あなたは、その最初のクロージャに対して関数呼び出しの一部として引数ラベルを書きません。関数呼び出しは、複数の後付クロージャを含むことができます;しかしながら、下の最初の幾つかの例はただ1つだけ後付クロージャを使います。

  1. func someFunctionThatTakesAClosure(closure: () -> Void) {
  2. // function body goes here(関数本文が、ここにきます)
  3. }
  4. // Here's how you call this function without using a trailing closure:(あなたが後付クロージャを使うことなくどのようにこの関数を呼ぶのかがここにあります:)
  5. someFunctionThatTakesAClosure(closure: {
  6. // closure's body goes here(クロージャの本文がここにきます)
  7. })
  8. // Here's how you call this function with a trailing closure instead:(あなたが代わりに後付クロージャでどのようにこの関数を呼ぶのかがここにあります:)
  9. someFunctionThatTakesAClosure() {
  10. // trailing closure's body goes here(後付クロージャの本文がここにきます)
  11. }

The string-sorting closure from the Closure Expression Syntax section above can be written outside of the sorted(by:) method’s parentheses as a trailing closure: 上のクロージャ式構文の節の文字列を分類するクロージャは、後付クロージャとしてsorted(by:)関数の括弧の外側に書かれることができます:

  1. reversedNames = names.sorted() { $0 > $1 }

If a closure expression is provided as the function’s or method’s only argument and you provide that expression as a trailing closure, you don’t need to write a pair of parentheses () after the function or method’s name when you call the function: あるクロージャ式が関数のもつまたはメソッドのもつ唯一の引数として提供され、そしてあなたが後付クロージャとしてその式を提供するならば、あなたがその関数を呼ぶ時に、一対の丸括弧()を関数やメソッドの名前の後に書く必要はありません:

  1. reversedNames = names.sorted { $0 > $1 }

Trailing closures are most useful when the closure is sufficiently long that it isn’t possible to write it inline on a single line. As an example, Swift’s Array type has a map(_:) method, which takes a closure expression as its single argument. The closure is called once for each item in the array, and returns an alternative mapped value (possibly of some other type) for that item. You specify the nature of the mapping and the type of the returned value by writing code in the closure that you pass to map(_:). クロージャがそれをただ1つの行の行内に書くことが可能でないほど長いとき、後付クロージャは最も役に立ちます。例として、スウィフトのArray型はmap(_:)メソッドを持ちます、それは、そのただ1つの引数としてクロージャ式をとります。クロージャは、配列の中の各項目に対して一度だけ呼ばれて、その項目のための代わりの対応付けされた(おそらく何か他の型の)値を返します。あなたは、マッピング(対応付け)の性質と返される値の型を、あなたがmap(_:)に渡すクロージャの中でコードを記述することによって指定します。

After applying the provided closure to each array element, the map(_:) method returns a new array containing all of the new mapped values, in the same order as their corresponding values in the original array. 提供されたクロージャを各配列要素に適用した後に、map(_:)メソッドは、新しい対応付けられる値の全てを、もとの配列のそれらの対応する値と同じ順序で含んでいる新しい配列を返します。

Here’s how you can use the map(_:) method with a trailing closure to convert an array of Int values into an array of String values. The array [16, 58, 510] is used to create the new array ["OneSix", "FiveEight", "FiveOneZero"]: ここに、あなたがInt値の配列をString値の配列に変えるために後付クロージャとともにmap(_:)メソッドをどのように使用できるかがあります。配列[16, 58, 510]は、新しい配列["OneSix", "FiveEight", "FiveOneZero"]をつくるために使われます:

  1. let digitNames = [
  2. 0: "Zero", 1: "One", 2: "Two", 3: "Three", 4: "Four",
  3. 5: "Five", 6: "Six", 7: "Seven", 8: "Eight", 9: "Nine"
  4. ]
  5. let numbers = [16, 58, 510]

The code above creates a dictionary of mappings between the integer digits and English-language versions of their names. It also defines an array of integers, ready to be converted into strings. 上のコードは、整数桁とそれらの名前の英語版の間で対応付けをする辞書を作成します。それはまた、文字列に変換される準備ができている整数の配列も定義します。

You can now use the numbers array to create an array of String values, by passing a closure expression to the array’s map(_:) method as a trailing closure: あなたは、現在、このnumbers配列をString値の配列をつくるために使うことが、あるクロージャ式を配列のmap(_:)メソッドに後付クロージャとして渡すことによって、可能です:

  1. let strings = numbers.map { (number) -> String in
  2. var number = number
  3. var output = ""
  4. repeat {
  5. output = digitNames[number % 10]! + output
  6. number /= 10
  7. } while number > 0
  8. return output
  9. }
  10. // strings is inferred to be of type [String](stringsは型[String]と推論されます)
  11. // its value is ["OneSix", "FiveEight", "FiveOneZero"](その値は["OneSix", "FiveEight", "FiveOneZero"]です)

The map(_:) method calls the closure expression once for each item in the array. You don’t need to specify the type of the closure’s input parameter, number, because the type can be inferred from the values in the array to be mapped. map(_:)メソッドは、配列の中の各項目に対して一度だけクロージャ式を呼びます。あなたはクロージャの入力パラメータ、numberの型を指定する必要がありません、なぜならその型は対応付けされる配列の値から推論されることが可能だからです。

In this example, the variable number is initialized with the value of the closure’s number parameter, so that the value can be modified within the closure body. (The parameters to functions and closures are always constants.) The closure expression also specifies a return type of String, to indicate the type that will be stored in the mapped output array. この例では、変数numberはこのクロージャの持つnumberパラメータの値を使って初期化されます、それでその値はクロージャ本体の内部で修正されることができます。(関数およびクロージャに対するパラメータは常に定数です。)クロージャ式はまた、Stringの戻り型を指定します、それによってマップされた出力配列の中に格納されることになる型を指し示します。

The closure expression builds a string called output each time it’s called. It calculates the last digit of number by using the remainder operator (number % 10), and uses this digit to look up an appropriate string in the digitNames dictionary. The closure can be used to create a string representation of any integer greater than zero. クロージャ式は、それが呼ばれるたびに、outputと呼ばれる文字列をつくります。それは、numberの最後の桁を剰余演算子を使用することによって計算して(number % 10)、この桁をdigitNames辞書で適切な文字列を捜すために使います。このクロージャは、ゼロより大きいあらゆる整数の文字列表現を作るために使われることが出来ます。

Note 注意

The call to the digitNames dictionary’s subscript is followed by an exclamation point (!), because dictionary subscripts return an optional value to indicate that the dictionary lookup can fail if the key doesn’t exist. In the example above, it’s guaranteed that number % 10 will always be a valid subscript key for the digitNames dictionary, and so an exclamation point is used to force-unwrap the String value stored in the subscript’s optional return value. digitNames辞書への呼び出しの添え字の後に感嘆符(!)が続きます、なぜなら、キーが存在しない場合は辞書検索が失敗し得ることを意味するために、辞書添え字がオプショナルの値を返すからです。上の例でnumber % 10は常にdigitNames辞書のための有効な添え字キーであることを求められます、なのでその添え字のオプショナルの戻り値に保管したString値を強制アンラップするために感嘆符が使われます。

The string retrieved from the digitNames dictionary is added to the front of output, effectively building a string version of the number in reverse. (The expression number % 10 gives a value of 6 for 16, 8 for 58, and 0 for 510.) digitNames辞書から取り出される文字列はoutput前方に加えられて、うまい具合に数の文字列版を逆の順序で造ります。(式数number % 10は、16のために658のために8510のために0の値を与えます)。

The number variable is then divided by 10. Because it’s an integer, it’s rounded down during the division, so 16 becomes 1, 58 becomes 5, and 510 becomes 51. number変数は、それから10で割られます。それが整数であるので、除算のときに端数を切り捨てられます、それで161に、585に、そして51051になります。

The process is repeated until number is equal to 0, at which point the output string is returned by the closure, and is added to the output array by the map(_:) method. この処理はnumber0に等しくなるまで繰り返されます、その時点でoutput文字列がクロージャによって返されて、そしてmap(_:)メソッドによって出力配列に加えられます。

The use of trailing closure syntax in the example above neatly encapsulates the closure’s functionality immediately after the function that closure supports, without needing to wrap the entire closure within the map(_:) method’s outer parentheses. 上の例での後付クロージャ構文の使用は、クロージャの機能性をクロージャが手助けする関数の直後に手際よく要約していて、クロージャ全体をmap(_:)メソッドの持つ外側の丸括弧の内部に包む必要はありません。

If a function takes multiple closures, you omit the argument label for the first trailing closure and you label the remaining trailing closures. For example, the function below loads a picture for a photo gallery: 関数が複数のクロージャを取るならば、あなたは最初の後付クロージャに対して引数ラベルを省きます、そしてあなたは残りの後付クロージャにラベルをつけます。例えば、下の関数はあるピクチャをフォトギャラリーに対してロードします:

  1. func loadPicture(from server: Server, completion: (Picture) -> Void, onFailure: () -> Void) {
  2. if let picture = download("photo.jpg", from: server) {
  3. completion(picture)
  4. } else {
  5. onFailure()
  6. }
  7. }

When you call this function to load a picture, you provide two closures. The first closure is a completion handler that displays a picture after a successful download. The second closure is an error handler that displays an error to the user. あなたがこの関数を呼び出してあるピクチャをロードする時、あなたは2つのクロージャを提供します。最初のクロージャはある完了ハンドラです、それはあるピクチャを成功したダウンロードの後に表示します。2番目のクロージャは、エラーハンドラです、それはエラーをユーザに対して表示します。

  1. loadPicture(from: someServer) { picture in
  2. someView.currentPicture = picture
  3. } onFailure: {
  4. print("Couldn't download the next picture.")
  5. }

In this example, the loadPicture(from:completion:onFailure:) function dispatches its network task into the background, and calls one of the two completion handlers when the network task finishes. Writing the function this way lets you cleanly separate the code that’s responsible for handling a network failure from the code that updates the user interface after a successful download, instead of using just one closure that handles both circumstances. この例において、loadPicture(from:completion:onFailure:)関数は、それのネットワークタスクをバックグラウンドへとディスパッチします、そして2つの完了ハンドラのうちの1つをネットワークタスクが終了する時に呼び出します。関数をこの方法で書くことは、あなたにネットワーク失敗を取り扱うことに責任を持つコードを、成功したダウンロードの後にユーザインターフェイスを更新するコードから分離させます。

Capturing Values 値を捕獲する

A closure can capture constants and variables from the surrounding context in which it’s defined. The closure can then refer to and modify the values of those constants and variables from within its body, even if the original scope that defined the constants and variables no longer exists. クロージャは、それが定義される周囲の前後関係から、定数と変数を捕獲(キャプチャ)できます。クロージャはそれから、その本文内からそれらの定数と変数の値に言及することや修正することができます、たとえその定数と変数を定義した本来のスコープがもはや存在しないとしてもです。

In Swift, the simplest form of a closure that can capture values is a nested function, written within the body of another function. A nested function can capture any of its outer function’s arguments and can also capture any constants and variables defined within the outer function. スウィフトにおいて、値をキャプチャできるクロージャの最も単純な形式は、別の関数の本文内に書かれる、入れ子にされた関数です。入れ子にされた関数は、その外側の関数の持つ引数の何でも捕獲することができ、また外側の関数の範囲内で定義されるどんな定数や変数でも捕獲することができます。

Here’s an example of a function called makeIncrementer, which contains a nested function called incrementer. The nested incrementer() function captures two values, runningTotal and amount, from its surrounding context. After capturing these values, incrementer is returned by makeIncrementer as a closure that increments runningTotal by amount each time it’s called. ここに、makeIncrementerと呼ばれる関数の例があります、それはincrementerと呼ばれる入れ子にされた関数を含みます。入れ子にされたincrementer()関数は、それを取り囲む前後関係から2つの値、runningTotalamountを捕獲します。これらの値を捕獲した後に、incrementermakeIncrementerによって、それが呼ばれるたびにrunningTotalamountによって増加させるクロージャとして返されます。

  1. func makeIncrementer(forIncrement amount: Int) -> () -> Int {
  2. var runningTotal = 0
  3. func incrementer() -> Int {
  4. runningTotal += amount
  5. return runningTotal
  6. }
  7. return incrementer
  8. }

The return type of makeIncrementer is () -> Int. This means that it returns a function, rather than a simple value. The function it returns has no parameters, and returns an Int value each time it’s called. To learn how functions can return other functions, see Function Types as Return Types. makeIncrementerの戻り型は、() -> Intです。これは、それが関数を返すことを意味します、単純なひとつの値ではなく。それが返す関数は、パラメータを持たず、それが呼ばれるたびにInt値を返します。関数が他の関数を返すことができる方法を学ぶために、戻り型としての関数型を見てください。

The makeIncrementer(forIncrement:) function defines an integer variable called runningTotal, to store the current running total of the incrementer that will be returned. This variable is initialized with a value of 0. makeIncrementer(forIncrement:)関数は、返されるincrementerの現時点での合計を格納するために、runningTotalと呼ばれる整数変数を定義します。この変数は、値0で初期化されます。

The makeIncrementer(forIncrement:) function has a single Int parameter with an argument label of forIncrement, and a parameter name of amount. The argument value passed to this parameter specifies how much runningTotal should be incremented by each time the returned incrementer function is called. The makeIncrementer function defines a nested function called incrementer, which performs the actual incrementing. This function simply adds amount to runningTotal, and returns the result. makeIncrementer(forIncrement:)関数は、forIncrementの引数ラベル、そしてamountのパラメータ名を持つ、ただ1つのIntパラメータを持ちます。このパラメータに渡された引き数の値は、返されたインクリメンタ関数(漸増器関数)が呼ばれるたびに、どのくらいrunningTotalが増やされなければならないかについて指定します。makeIncrementer関数はincrementerと呼ばれる入れ子にされた関数を定義します、それは、実際に増やすことを実行します。この関数は、単にamountrunningTotalに加えて、結果を返します。

When considered in isolation, the nested incrementer() function might seem unusual: 切り離して考えたとき、入れ子にされたincrementer()関数は普通でないものに見えるかもしれません:

  1. func incrementer() -> Int {
  2. runningTotal += amount
  3. return runningTotal
  4. }

The incrementer() function doesn’t have any parameters, and yet it refers to runningTotal and amount from within its function body. It does this by capturing a reference to runningTotal and amount from the surrounding function and using them within its own function body. Capturing by reference ensures that runningTotal and amount don’t disappear when the call to makeIncrementer ends, and also ensures that runningTotal is available the next time the incrementer function is called. incrementer()関数には全くパラメータがありません、それなのに、それはその関数本文内からrunningTotalamountに言及します。それは、それを囲んでいる関数からrunningTotalamountへの参照を捕獲して、それらをそれ自身の関数本文内で使うことによってこれを行います。参照を捕獲することは、runningTotalamountが、makeIncrementerへの呼び出しが終わる時に消えてなくならないことを確かなものにします、そしてまたrunningTotalが、incrementer関数が呼ばれる次の時に利用可能であることを確実にします。

Note 注意

As an optimization, Swift may instead capture and store a copy of a value if that value isn’t mutated by a closure, and if the value isn’t mutated after the closure is created. ひとつの最適化として、その値がクロージャによって変化させられないならば、そしてその値がクロージャが作成された後に変化されられないならば、スウィフトはそれよりむしろ値のコピーをキャプチャして保管するかもしれません。

Swift also handles all memory management involved in disposing of variables when they’re no longer needed. スウィフトはまた、それがもはや必要とされないとき変数を処分することに関わるすべての記憶管理を取り扱います。

Here’s an example of makeIncrementer in action: 動作しているmakeIncrementerの例がここにあります:

  1. let incrementByTen = makeIncrementer(forIncrement: 10)

This example sets a constant called incrementByTen to refer to an incrementer function that adds 10 to its runningTotal variable each time it’s called. Calling the function multiple times shows this behavior in action: この例は、incrementByTenと呼ばれる定数を、それが呼ばれるたびに10をそのrunningTotal変数に加えるあるインクリメンタ関数に言及するように設定します。この関数を複数回呼ぶことは、活動中にこの挙動を示します:

  1. incrementByTen()
  2. // returns a value of 10(値10を返す)
  3. incrementByTen()
  4. // returns a value of 20(値20を返す)
  5. incrementByTen()
  6. // returns a value of 30(値30を返す)

If you create a second incrementer, it will have its own stored reference to a new, separate runningTotal variable: あなたが第2のインクリメンタをつくるならば、それは、独自に格納された、ある新しい、別個のrunningTotal変数への参照を持ちます:

  1. let incrementBySeven = makeIncrementer(forIncrement: 7)
  2. incrementBySeven()
  3. // returns a value of 7(値7を返す)

Calling the original incrementer (incrementByTen) again continues to increment its own runningTotal variable, and doesn’t affect the variable captured by incrementBySeven: 最初のインクリメンタ(incrementByTen)を再び呼ぶことは、それ独自のrunningTotal変数を増加させることを継続します、そしてincrementBySevenによってキャプチャされる変数に影響しません。

  1. incrementByTen()
  2. // returns a value of 40(値40を返す)

Note 注意

If you assign a closure to a property of a class instance, and the closure captures that instance by referring to the instance or its members, you will create a strong reference cycle between the closure and the instance. Swift uses capture lists to break these strong reference cycles. For more information, see Strong Reference Cycles for Closures. あなたが、あるクロージャをあるクラスインスタンスのプロパティに代入して、そしてクロージャがそのインスタンスを、インスタンスまたはそのメンバー(属するもの)に言及することによって捕獲するならば、あなたはクロージャとインスタンスの間で強い参照循環をつくります。スウィフトは、これらの強い参照循環を壊すために捕獲リストを使用します。詳細は、クロージャのための強い参照循環を見てください。

Closures Are Reference Types クロージャは参照型です

In the example above, incrementBySeven and incrementByTen are constants, but the closures these constants refer to are still able to increment the runningTotal variables that they have captured. This is because functions and closures are reference types. 上の例で、incrementBySevenincrementByTenは定数です、しかしこれらの定数が言及するクロージャはそれでもなお、それらが捕獲したrunningTotal変数を増加させることができます。これは、関数とクロージャが参照型であるからです。

Whenever you assign a function or a closure to a constant or a variable, you are actually setting that constant or variable to be a reference to the function or closure. In the example above, it’s the choice of closure that incrementByTen refers to that’s constant, and not the contents of the closure itself. あなたが関数やクロージャを定数または変数に代入するときはいつでも、あなたは実際はその定数または変数が関数やクロージャへの参照であると設定しています。上の例では、それは「クロージャの選択」です、それがincrementByTen参照するものであり、それは定数であり、そしてクロージャ自身の内容ではありません。

This also means that if you assign a closure to two different constants or variables, both of those constants or variables refer to the same closure. これはまた、あなたがクロージャを2つの異なる定数または変数に代入するならば、それらの定数または変数の両方とも同じクロージャに言及することを意味するでしょう。

  1. let alsoIncrementByTen = incrementByTen
  2. alsoIncrementByTen()
  3. // returns a value of 50(値50を返す)
  4. incrementByTen()
  5. // returns a value of 60(値60を返す)

The example above shows that calling alsoIncrementByTen is the same as calling incrementByTen. Because both of them refer to the same closure, they both increment and return the same running total. 上の例は、alsoIncrementByTenを呼び出すことはincrementByTenを呼び出す事と同じであるのを示します。それらの両方ともが同じクロージャを参照することから、それらは両方とも漸増しますそして同じ実行総数を返します。

Escaping Closures 脱出クロージャ

A closure is said to escape a function when the closure is passed as an argument to the function, but is called after the function returns. When you declare a function that takes a closure as one of its parameters, you can write @escaping before the parameter’s type to indicate that the closure is allowed to escape. クロージャが引数として関数に渡される、しかしその関数が戻った後に呼び出されるとき、クロージャは関数を脱出すると言われます。あなたがある関数、それのパラメータの1つとしてクロージャをとるものを宣言する時、あなたは@escapingをパラメータの型の前に書くことによって、そのクロージャが脱出を許可されるのを指し示すことができます。

One way that a closure can escape is by being stored in a variable that’s defined outside the function. As an example, many functions that start an asynchronous operation take a closure argument as a completion handler. The function returns after it starts the operation, but the closure isn’t called until the operation is completed—the closure needs to escape, to be called later. For example: クロージャが脱出できる1つの方法は、関数の外側で定義される変数に格納されることによってです。例として、非同期の演算を開始する多くの関数は、クロージャ引数を完了ハンドラとして取ります。関数は、それが演算を開始した後に戻ります、しかしクロージャはその演算が完了されるまで呼び出されません—このクロージャは脱出すること、後で呼び出されること、を必要とします。例えば:

  1. var completionHandlers: [() -> Void] = []
  2. func someFunctionWithEscapingClosure(completionHandler: @escaping () -> Void) {
  3. completionHandlers.append(completionHandler)
  4. }

The someFunctionWithEscapingClosure(_:) function takes a closure as its argument and adds it to an array that’s declared outside the function. If you didn’t mark the parameter of this function with @escaping, you would get a compile-time error. someFunctionWithEscapingClosure(_:)関数は、クロージャをそれの引数として取ります、そしてそれを関数の外側で宣言される配列に加えます。あなたがこの関数のパラメータを@escapingで印しないならば、あなたはコンパイル時エラーを得るでしょう。

An escaping closure that refers to self needs special consideration if self refers to an instance of a class. Capturing self in an escaping closure makes it easy to accidentally create a strong reference cycle. For information about reference cycles, see Automatic Reference Counting. selfを参照する脱出クロージャは、もしselfがあるクラスのインスタンスを参照するならば、特別な配慮を必要とします。selfを脱出クロージャの中にキャプチャすることは、誤って強い参照循環を作りやすくします。参照循環についての情報として、自動参照カウントを見てください。

Normally, a closure captures variables implicitly by using them in the body of the closure, but in this case you need to be explicit. If you want to capture self, write self explicitly when you use it, or include self in the closure’s capture list. Writing self explicitly lets you express your intent, and reminds you to confirm that there isn’t a reference cycle. For example, in the code below, the closure passed to someFunctionWithEscapingClosure(_:) refers to self explicitly. In contrast, the closure passed to someFunctionWithNonescapingClosure(_:) is a nonescaping closure, which means it can refer to self implicitly. 通常、クロージャは変数それらのキャプチャを、それらをクロージャの本体の中で使うことによって暗黙的に行います、しかしこの場合にはあなたは明示的にする必要があります。あなたがselfをキャプチャしたいならば、selfを明示的にあなたがそれを使う時に書いてください、またはselfをクロージャのもつキャプチャリストの中に含めてください。selfを明示的に書くことは、あなたにあなたの意図を表現させます、そして参照循環がないことを確認するのをあなたに思い出させます。例えば、下のコードにおいて、someFunctionWithEscapingClosure(_:)に渡されるクロージャは、selfを明示的に参照します。対照的に、someFunctionWithNonescapingClosure(_:)に渡されるクロージャは、非脱出クロージャです、そのことは、それがselfを暗黙的に参照できるのを意味します。

  1. func someFunctionWithNonescapingClosure(closure: () -> Void) {
  2. closure()
  3. }
  4. class SomeClass {
  5. var x = 10
  6. func doSomething() {
  7. someFunctionWithEscapingClosure { self.x = 100 }
  8. someFunctionWithNonescapingClosure { x = 200 }
  9. }
  10. }
  11. let instance = SomeClass()
  12. instance.doSomething()
  13. print(instance.x)
  14. // Prints "200"
  15. completionHandlers.first?()
  16. print(instance.x)
  17. // Prints "100"

Here’s a version of doSomething() that captures self by including it in the closure’s capture list, and then refers to self implicitly: ここにdoSomething()のある変異版があります、それはselfを、それをクロージャのもつキャプチャリストの中に含めることによってキャプチャします、そしてそれからselfを暗黙的に参照します:

  1. class SomeOtherClass {
  2. var x = 10
  3. func doSomething() {
  4. someFunctionWithEscapingClosure { [self] in x = 100 }
  5. someFunctionWithNonescapingClosure { x = 200 }
  6. }
  7. }

If self is an instance of a structure or an enumeration, you can always refer to self implicitly. However, an escaping closure can’t capture a mutable reference to self when self is an instance of a structure or an enumeration. Structures and enumerations don’t allow shared mutability, as discussed in Structures and Enumerations Are Value Types. selfがある構造体または列挙のインスタンスであるならば、あなたは常にselfを暗黙的に参照できます。しかしながら、脱出クロージャはselfに対する可変参照をキャプチャすることが、selfが構造体または列挙のインスタンスである場合はできません。構造体と列挙は、共有された可変性を許可しません、構造体と列挙は値型ですで記述されるように。

  1. struct SomeStruct {
  2. var x = 10
  3. mutating func doSomething() {
  4. someFunctionWithNonescapingClosure { x = 200 } // Ok
  5. someFunctionWithEscapingClosure { x = 100 } // Error
  6. }
  7. }

The call to the someFunctionWithEscapingClosure function in the example above is an error because it’s inside a mutating method, so self is mutable. That violates the rule that escaping closures can’t capture a mutable reference to self for structures. someFunctionWithEscapingClosure関数への呼び出しは上の例においてエラーです、なぜならそれがある可変メソッドの内部にあるためです、それでselfは可変です。それは、脱出クロージャはselfへの可変参照を構造体についてはキャプチャできないという規則に違反します。

Autoclosures 自動クロージャ

An autoclosure is a closure that’s automatically created to wrap an expression that’s being passed as an argument to a function. It doesn’t take any arguments, and when it’s called, it returns the value of the expression that’s wrapped inside of it. This syntactic convenience lets you omit braces around a function’s parameter by writing a normal expression instead of an explicit closure. 自動クロージャは、自動的に作成されて、引数として関数に渡されている式を包み込むクロージャです。それは、全く引数を取りません、そしてそれが呼ばれる時、その内部に包み込まれた式の値を返します。この統語上の便宜は、明示的なクロージャの代わりに通常の関数を書くことによって、あなたに関数のパラメータのまわりの波括弧を省略させます。

It’s common to call functions that take autoclosures, but it’s not common to implement that kind of function. For example, the assert(condition:message:file:line:) function takes an autoclosure for its condition and message parameters; its condition parameter is evaluated only in debug builds and its message parameter is evaluated only if condition is false. 自動クロージャを取る関数を呼び出すのは普通です、しかしそのような関数を実装するのは一般的ではありません。例えば、assert(condition:message:file:line:)関数は自動クロージャをそれのconditionmessageパラメータとして取ります;それのconditionパラメータはデバッグビルドにおいてのみ評価されます、そしてそれのmessageパラメータはconditionfalseである場合にのみ評価されます。

An autoclosure lets you delay evaluation, because the code inside isn’t run until you call the closure. Delaying evaluation is useful for code that has side effects or is computationally expensive, because it lets you control when that code is evaluated. The code below shows how a closure delays evaluation. 自動クロージャは、あなたに評価を延期させます、内部のコードはあなたがそのクロージャを呼び出すまで実行されないからです。評価を遅らせることは、副作用を持つまたは計算的に高くつくコードに対して有用です、なぜならそれがあなたに何時そのコードが評価されるかを制御させるからです。下のコードは、どのようにクロージャが評価を遅らすかを示します。

  1. var customersInLine = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
  2. print(customersInLine.count)
  3. // Prints "5"
  4. let customerProvider = { customersInLine.remove(at: 0) }
  5. print(customersInLine.count)
  6. // Prints "5"
  7. print("Now serving \(customerProvider())!")
  8. // Prints "Now serving Chris!"(今クリスに対応中!)
  9. print(customersInLine.count)
  10. // Prints "4"

Even though the first element of the customersInLine array is removed by the code inside the closure, the array element isn’t removed until the closure is actually called. If the closure is never called, the expression inside the closure is never evaluated, which means the array element is never removed. Note that the type of customerProvider isn’t String but () -> String—a function with no parameters that returns a string. たとえcustomersInLine配列の最初の要素がクロージャ内部のコードによって取り除かれるとしても、その配列要素はクロージャが実際に呼び出されるまで実行されません。このクロージャが決して呼び出されないならば、クロージャ内部の式は決して評価されません、それは配列要素が決して取り除かれないことを意味します。注意すべきは、customerProviderの型はStringではなく() -> String — ある文字列を返すパラメータのない関数 — であることです。

You get the same behavior of delayed evaluation when you pass a closure as an argument to a function. あなたが同じ挙動の延期した評価を得るのは、あなたがクロージャを引数として関数に渡す時です。

  1. // customersInLine is ["Alex", "Ewa", "Barry", "Daniella"](customersInLine(並んでいる顧客)は、["Alex", "Ewa", "Barry", "Daniella"]です)
  2. func serve(customer customerProvider: () -> String) {
  3. print("Now serving \(customerProvider())!")
  4. }
  5. serve(customer: { customersInLine.remove(at: 0) } )
  6. // Prints "Now serving Alex!"(今アレックスに対応中!)

The serve(customer:) function in the listing above takes an explicit closure that returns a customer’s name. The version of serve(customer:) below performs the same operation but, instead of taking an explicit closure, it takes an autoclosure by marking its parameter’s type with the @autoclosure attribute. Now you can call the function as if it took a String argument instead of a closure. The argument is automatically converted to a closure, because the customerProvider parameter’s type is marked with the @autoclosure attribute. 上で記載されるserve(customer:)関数は、次の顧客の名前を返す、ある明示的なクロージャを取ります。下のバージョンのserve(customer:)は同じ演算を実行します、しかし明示的なクロージャを取るのではなく、それは自動クロージャを、それのパラメータの型を@autoclosure属性で記することによって取ります。今やあなたはこの関数を、まるでそれがクロージャではなくString引数を取るかのように呼び出せます。引数は、自動的にクロージャに変換されます、なぜならcustomerProviderパラメータの型は@autoclosure属性で印されるからです。

  1. // customersInLine is ["Ewa", "Barry", "Daniella"](customersInLine(並んでいる顧客)は、["Ewa", "Barry", "Daniella"]です)
  2. func serve(customer customerProvider: @autoclosure () -> String) {
  3. print("Now serving \(customerProvider())!")
  4. }
  5. serve(customer: customersInLine.remove(at: 0))
  6. // Prints "Now serving Ewa!"(今エヴァに対応中!)

Note 注意

Overusing autoclosures can make your code hard to understand. The context and function name should make it clear that evaluation is being deferred. 自動クロージャの使いすぎは、あなたのコードを理解しにくくする可能性があります。文脈と関数名は、評価が猶予されていることを明確にしなければなりません。

If you want an autoclosure that’s allowed to escape, use both the @autoclosure and @escaping attributes. The @escaping attribute is described above in Escaping Closures. あなたが脱出を許可される自動クロージャを望むならば、@autoclosure@escaping属性を両方とも使ってください。@escaping属性は、上の脱出クロージャで解説されます。

  1. // customersInLine is ["Barry", "Daniella"](customersInLine(並んでいる顧客)は、["Barry", "Daniella"]です)
  2. var customerProviders: [() -> String] = []
  3. func collectCustomerProviders(_ customerProvider: @autoclosure @escaping () -> String) {
  4. customerProviders.append(customerProvider)
  5. }
  6. collectCustomerProviders(customersInLine.remove(at: 0))
  7. collectCustomerProviders(customersInLine.remove(at: 0))
  8. print("Collected \(customerProviders.count) closures.")
  9. // Prints "Collected 2 closures."(「2つのクロージャが集められた。」を出力します)
  10. for customerProvider in customerProviders {
  11. print("Now serving \(customerProvider())!")
  12. }
  13. // Prints "Now serving Barry!"(今バリーに対応中!)
  14. // Prints "Now serving Daniella!"(今ダニエラに対応中!)

In the code above, instead of calling the closure passed to it as its customerProvider argument, the collectCustomerProviders(_:) function appends the closure to the customerProviders array. The array is declared outside the scope of the function, which means the closures in the array can be executed after the function returns. As a result, the value of the customerProvider argument must be allowed to escape the function’s scope. 上のコードにおいて、それのcustomerProvider引数としてそれに渡されるクロージャを呼び出す代わりに、collectCustomerProviders(_:)関数は、そのクロージャをcustomerProviders配列に追加します。この配列は関数のスコープの外側で宣言されます、それは配列の中のクロージャが関数が戻った後で実行されることができるのを意味します。その結果、customerProvider引数の値は関数のスコープを脱出することを許されなければなりません。

Functions 関数

Enumerations 列挙