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.”
闭包是可以传递并在你的代码中使用的具有某种功能的独立的代码块儿。Swift中的闭包类似于C和OC中的blocks并且和其他程序语言中的lambdas表达式类似。
“Closures can capture and store references to any constants and variables from the context in which they are defined. This is known as closing over those constants and variables,hence the name “closures”. Swift handles all of the memory management of capturing for you.”
闭包可以从他们被定义的上下文中捕获以及存储常量和变量的引用。这就是所说的关闭那些常量和变量,因此被叫做闭包。Swift为你处理所有捕获的内存管理工作。
“NOTE
“Global and nested functions,as introduced in Functions,are actually special cases of closures. Closures take one of three forms:”
“Global functions are closures that have a name and do not 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”
Swift的闭包表达式有一种干净,明朗的风格,并且对于鼓励在一般的场景中使用简洁,clutter自由的语法做出了优化。这些优化包括:
从上下文中推断参数和返回值类型
从单一表达式闭包返回隐式返回值
简约参数名
结尾闭包语法
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 is“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 that take other functions as one or more of their arguments.
嵌套函数,就像在“嵌套函数”章节中介绍的,是一种方便的命名和定义字包含代码块的方式。然而,对于书写一些不需要完整声明和命名的较短的类似于函数的结构体是很有用的。当你使用一种以其他函数作为他的一个或者更多参数的函数时,你会发现这确实是真的。
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 function over several iterations,each of which expresses the same functionality in a more succinct way.”
闭包表达式是一种以简洁,紧凑的语法写出内联闭包的方式。闭包表达式提供了集中书写闭包的语法优化,方式简短,并且不丢失精确度与含义。以下闭包表达式的例子列举了这些优化,一个排序函数通过几次迭代得到了提炼,并且每次迭代都用一种更高效的方式表达了同样的功能。
The Sorted Function
“Swift’s standard library provides a function called sorted,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 function 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 is not modified by the sorted function.”
Swift的标准库中提供了一种叫做排序的函数,他把一个已知类型的数组中的值进行排序,基于你提供的排序闭包的输出结果。一旦它完成了排序过程,排序函数就会返回一个与旧数组包含元素类型相同大小相同的新数组,并且元素有了正确的顺序,而原始数组并没有被排序函数修改。
“The closure expression examples below use the sorted function to sort an array of String values in reverse alphabetical order. Here’s the initial array to be sorted:”
以下的闭包表达式举例使用排序函数将一组字符串类型的元素按逆序字母顺序排序。以下是被排序的原始数组:
“let names = ["Chris","Alex","Ewa","Barry","Daniella"]”
“The sorted function takes two arguments:
An array of values of a known type.
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.”
排序函数有两个参数:
已知元素类型的一个数组
一个带有两个参数的闭包,这连个参数与数组内容有相同的类型,并且值一旦被排序就会返回一个布尔值以表明第一个值是应该在第二个值之前还是之后出现。如果第一个值应该在第二个值之前出现,这个排序闭包就需要返回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)-> Bool
“One way to provide the sorting closure is to write a normal function of the correct type,and to pass it in as the sorted function’s second parameter:”
一种提供排序闭包的方法是写一个类型正确的普通函数,并且将它传给排序函数作为第二个参数
“func backwards(s1: String,s2: String) -> Bool { return s1 > s2 } var reversed = sorted(names,backwards) // reversed is equal to ["Ewa","Daniella","Chris","Alex"]”
“If the first string (s1) is greater than the second string (s2),the backwards 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比第二个字符串要大,逆序函数将会返回true,表示在排序好的数组中s1应该在s2之前出现。对于字符串中的字符,“比...大”意味着“在字母表中后出现的”。这就意味着字母“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:”
闭包表达式语法 ,闭包表达式语法有以下几种形式
“{ (parameters) -> return type in statements }”
“Closure expression Syntax can use constant parameters,variable parameters,and inout parameters. Default values cannot be provided. Variadic parameters can be used if you name the variadic parameter and place it last in the parameter list. Tuples can also be used as parameter types and return types.”
闭包表达式语法合适使用常量参数,变量参数和输入输出参数。不能提供默认值。如果你命名了可变参数并且将它放在了参数列表中最后的位置它将会被使用。元祖也可以并用作参数类型和返回值类型。
“The example below shows a closure expression version of the backwards function from earlier:”
下面的例子显示了较之之前的版本的一个逆序函数的闭包表达式版本。
“reversed = sorted(names,{ (s1: String,s2: String) -> Bool in return s1 > s2 })”
“Note that the declaration of parameters and return type for this inline closure is identical to the declaration from the backwards function. In both cases,it is 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.”
注意这个内联闭包的参数和返回值的生命和逆序函数的声明是相同的。在这两者中,它被写作(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:”
因为闭包的主体太短了,所以它可以被写作简单的一行
“reversed = sorted(names,s2: String) -> Bool in return s1 > s2 } )”
“This illustrates that the overall call to the sorted function has remained the same. A pair of parentheses still wrap the entire set of arguments for the function. However,one of those arguments is now an inline closure.”
这个证明了排序函数的整体调用还保持原状。一对圆括号仍然包含了这个函数的所有参数。然而,其中一个蚕食现在已经是内联闭包了。
“Inferring Type From Context”
从上下文中推断类型
“Because the sorting closure is passed as an argument to a function,Swift can infer the types of its parameters and the type of the value it returns from the type of the sorted function’s second parameter. This parameter is expecting a function of type (String,String) -> Bool. This means that the (String,String) and Bool types do not 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:”
由于排序闭包被作为参数传给函数,Swift可以从排序函数的第二个参数的类型中推断他的参数的类型和它的返回值的类型。这个参数是函数类型的(String,String) -> Bool。这意味着(String,String)和布尔类型不需要作为闭包表达式定义的一部分被写出来。因为所有的类型都可以被推断,箭头->和圆括号也可以被省略。
“reversed = sorted(names,{ s1,s2 in return s1 > s2 } )”
“It is always possible to infer the parameter types and return type when passing a closure to a function 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 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 function,the purpose of the closure is clear from the fact that sorting is taking place,and it is safe for a reader to assume that the closure is likely to be working with String values,because it is assisting with the sorting of an array of strings.”
虽然如此,如果你愿意你仍然可以写下精确的类型,并且如果他能避免你的代码含糊不清这样的做法将会被鼓励。在排序函数的例子中,相对于排序正在发生的事实闭包的目的更为清晰,并且如果用户假定闭包可能通过字符串类型使用那也将是安全的,因为他正在帮助一个字符串数组排序。
“Implicit Returns from Single-Expression Closures”
单一表达式闭包中的模糊返回值
“Single-expression closures can implicitly return the result of their single expression by omitting the return keyword fromtheir declaration,as in this version of the prevIoUs example:”
单一表达式闭包可以通过从声明中省略return关键字隐式地返回单一表达式的结果,就像之前的例子在下面的版本中的那样:
“reversed = sorted(names,s2 in s1 > s2 } )”
“Here,the function type of the sorted function’s second 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 is no ambiguity,and the return keyword can be omitted.”
在这儿,通过排序函数的第二个参数的函数类型可以更清楚的看到闭包必须返回一个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.”
Swift自动为内联闭包提供了现成的参数名,通过使用$0,$2等等来指向闭包的参数值。
“If you use these shorthand argument names within your closure expression,you can omit the closure’s argument list from its definition,and the number and type of the shorthand argument names will be inferred from the expected function type. The in keyword can also be omitted,because the closure expression is made up entirely of its body:”
如果你在你的闭包表达式中使用这些现成的参数名,你可以闭包的定义中省略了他的参数列表,现成的参数名字的数量和类型将会通过特定的函数类型来推断出来。in关键字也可以被省略了,因为闭包表达式都是通过他的主体形成的
“reversed = sorted(names,{ $0 > $1 } )”
“Here,$0 and $1 refer to the closure’s first and second String arguments.”
在这儿,$0和$1指的是闭包的第一个和第二个参数
Operator Functions
操作符函数
“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 function that has two parameters of type String,and returns a value of type Bool. This exactly matches the function type needed for the sorted function’s second parameter. Therefore,you can simply pass in the greater-than operator,and Swift will infer that you want to use its string-specific implementation:”
其实还有一种更加简洁的方式来写上述的闭包表达式。Swift的字符串类型定义了关于字符串对于比较运算符的实施实际上等同于有两个字符串参数的函数,并且返回Bool类型的值。这个精确地符合了排序函数中第二个参数所需要的函数类型。因此,你只需要传入比较运算符,Swift就能推断出你想要使用他的对应字符串的特定的实施方法。
reversed = sorted(names,>)
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. A trailing closure is a closure expression that is written outside of (and after) the parentheses of the function call it supports:”
如果你需要将一个闭包表达式传给一个函数作为函数最后一个参数并且闭包表达式很长,将它作为一个尾随闭包来写将会是很有用的。尾随闭包就是一个闭包表达式但是写在他所支持的函数调用的括号的外面或者之后的。
“func someFunctionThatTakesAClosure(closure: () -> ()) { // function body goes here } // here's how you call this function without using a trailing closure: someFunctionThatTakesAClosure({ // closure's body goes here }) // here's how you call this function with a trailing closure instead: someFunctionThatTakesAClosure() { // trailing closure's body goes here } ”
If a closure expression is provided as the function’s only argument and you provide that expression as a trailing closure,you do not need to write a pair of parentheses () after the function’s name when you call the function.”
如果一个闭包表达式是某个函数唯一的参数并且你将其写成尾随闭包,那么当你调用函数的时候不需要在函数名后面写小括号
“The string-sorting closure from the Closure Expression Syntax section above can be written outside of the sorted function’s parentheses as a trailing closure:”
上述的字符串排序闭包可以写在函数的小括号外面作为尾随闭包。
“reversed = sorted(names) { $0 > $1 }”
“Trailing closures are most useful when the closure is sufficiently long that it is not 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. The nature of the mapping and the type of the returned value is left up to the closure to specify.”
当一个闭包特别长不太容易以闭包表达式表达的时候尾随闭包就会特别有效。例如,Swift的数组类型 有一个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"]:”
下面就是你怎么样用一个尾随闭包将一个整形数组装换成字符串数组。数组[16,510]被用来创建新数组["OneSix","FiveOneZero"];
“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,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. Note that the call to numbers.map does not need to include any parentheses after map,because the map(_:) method has only one parameter,and that parameter is provided as a trailing closure:”
现在,你可以通过给数组的map方法传一个闭包作为尾随闭包,将一个数字数组装换成字符串数组。注意调用numbers.map不需要在map后面添加任何的小括号,因为map方法只有一个参数,并且那个参数是一个尾随闭包。
“let strings = numbers.map { (var number) -> String in var output = "" while number > 0 { output = digitNames[number % 10]! + output number /= 10 } return output } // strings is inferred to be of type [String] // its value is ["OneSix","FiveOneZero"]”
“The map(_:) method calls the closure expression once for each item in the array. You do not 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的类型,因为类型可以从要被执行map操作的数组中被推断出来。
“In this example,the closure’s number parameter is defined as a variable parameter,as described in Constant and Variable Parameters,so that the parameter’s value can be modified within the closure body,rather than declaring a new local variable and assigning the passed number value to it. The closure expression also specifies a return type of String,to indicate the type that will be stored in the mapped outputarray.
在这个例子中,闭包的number参数被定义为一个可变的参数,就像常量和变量参数中描述的那样,所以参数的值可以在闭包体内被修改,而不需要再声明一个本地的变量再把值传递给它。闭包表达式也规定了字符串类型的返回值,表明了map之后返回数组的元素类型。
“The closure expression builds a string called output each time it is 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 number greater than zero.”
每次调用闭包表达式,它都会创建一个叫做output的字符串。它通过使用取余运算计算出number的最后一位,然后通过这个数字在数字名称字典中取出一个字符串。闭包可以创建任何大于零的整数的字符型表示。
“NOTE
The call to the digitNames dictionary’s subscript is followed by an exclamation mark (!),because dictionary subscripts return an optional value to indicate that the dictionary lookup can fail if the key does not exist. In the example above,it is guaranteed that number % 10 will always be a valid subscript key for the digitNames dictionary,and so an exclamation mark is used to force-unwrap the String value stored in the subscript’s optional return value.”
字典下标后面跟着一个感叹号,因为从字典中取值会返回一个可选类型,因为如果key不存在就可能查询失败。在上述例子中,能够保证对于数字名称字典来说number %10将会总是一个有效的key,因为感叹号被用来强制解包出可选的返回值中存储的字符串。
“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.)”
从数字名称字典中获取的字符串被加在output的前面,有效的创造了逆序的数字的字符串版本。(表达式number % 10会从16取得6,从58取得8,从510取得0)
“The number variable is then divided by 10. Because it is an integer,it is rounded down during the division,so 16 becomes 1,58 becomes 5,and 510 becomes 51.”
变量number除以10.因为是整数,所以在除法中末尾被舍去,所以16变为1,58变为5,510变为51.
“The process is repeated until number /= 10 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 function.
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 function’s outer parentheses.”
知道number /=10 等于0时重复运算才结束,此时字符串被闭包返回,并被map函数加在ouput数组中。
上例中尾随闭包语法在函数后整洁封装了具体的闭包功能,而不再需要将整个闭包包裹在map
函数的括号内。
Capturing Values
捕获值
“A closure can capture constants and variables from the surrounding context in which it is 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.”
在Swift中,闭包捕获值的最简单的形式是一个嵌套函数,即写在另在一个函数体中的函数。一个嵌套函数可以捕获外部函数的参数和外部函数定义的任何常量和变量。
“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 is called.”
以下是一个叫做makeIncrementer的函数的例子,它包含了一个嵌套函数叫做incrementer.嵌套函数从它的上下文中捕获了两个值,runningTotal和amount。在捕获了这些值之后,incremented被makeIncrementer作为闭包被返回,并且incrementer每次被调用都会在runningTotal上加上amount.
“func makeIncrementer(forIncrement amount: Int) -> () -> Int { var runningTotal = 0 func incrementer() -> Int { runningTotal += amount return runningTotal } return incrementer } ”
“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 is called. To learn how functions can return other functions,see Function Types as Return Types.”
makeIncrementer的返回值类型是()-> Int.这意味着它返回一个函数,而不是一个简单的值。它返回的函数没有参数,但在每次调用的时候返回一个int类型的值。想知道函数怎样返回另外一个函数,请看 Function Types as Return Types
“The makeIncrementer 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函数定义了一个叫做runingTotal的整形变量,它是用来存储将会被incrementer返回的当前的runningTotal的值。这个变量初始化为0.
“The makeIncrementer function has a single Int parameter with an external name of forIncrement,and a local 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.”
makeIncremenyer函数有一个整数类型的参数,外部参数名叫做forIncrement,内部参数名叫做amount.这个参数的参数值具体规定了incrementer每次被调用时runningTotal被加多少。
“makeIncrementer defines a nested function called incrementer,which performs the actual incrementing. This function simply adds amount to runningTotal,and returns the result.”
makeIncrementer定义了一个叫做incrementer的嵌套函数,而这个函数实际在执行着增量运算。这个函数就是在RunningTotal上加上amount,然后返回结果。
“When considered in isolation,the nested incrementer function might seem unusual:”
当隔离出这个嵌套的incrementer函数来看,可能看起来有点不正常
“func incrementer() -> Int { runningTotal += amount return runningTotal }”
“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 the existing values of runningTotal and amount from its surrounding function and using them within its own function body.”
incrementer函数没有任何参数,但是他从他的函数体内引用了RunningTotal和amount。它从他的周围函数体重捕获了runningTotal和amount的值并在它自己的函数体重使用它们。
“Because it modifies the runningTotal variable each time it is called,incrementer captures a reference to the current runningTotal variable,and not just a copy of its initial value. Capturing a reference ensures that runningTotal does not disappear when the call to makeIncrementer ends,and ensures that runningTotal is available the next time the incrementer function is called..”
由于每次调用它都修改了runningTotal的值,incrementer捕获了当前runningTotal变量的一个参考,而不是它的初始值的一个副本。捕获引用保证了当makeIncrementer的调用结束后runningTotal不会消失,并且保证了runningTotal在下次incrementer被调用时仍然可用。
“However,because it does not modify amount,and amount is not mutated outside it,incrementer actually captures and stores a copy of the value stored in amount. This value is stored along with the new incrementer function.”
然而,因为它没有修改amount,amount在它之外也没有变化,incremented实际上捕获并存储了一份存储在amount中的值的copy。这个值将伴随这新的增量函数被存储。
“NOTE
Swift determines what should be captured by reference and what should be copied by value. You don’t need to annotate amount or runningTotal to say that they can be used within the nested incrementer function. Swift also handles all memory management involved in disposing of runningTotal when it is no longer needed by the incrementer function.”
Swift规定了什么应该通过引用捕获而什么是通过拷贝捕获的。你不需要通过注释来说amount或者runningTotal可以在嵌套函数incrementer内部使用。Swift也会处理当incrementer函数不再需要runningTotal时的所有的内存管理工作。
“Here’s an example of makeIncrementer in action:”
下面是一个makeIncrementer在实际中的一个例子
“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 is called. Calling the function multiple times shows this behavior in action:”
这个例子创建了一个叫做incrementByTen的例子来指向一个增量函数,这个增量函数每次被调用时RunningTotal都会加10.实际中多次调用这个函数的表现如下:
“incrementByTen() // returns a value of 10 incrementByTen() // returns a value of 20 incrementByTen() // returns a value of 30”
“If you create a second incrementer,it will have its own stored reference to a new,separate runningTotal variable:”
如果你创建了第二个incrementer,它将会指向一个新的独立的runningTotal变量。
“let incrementBySeven = makeIncrementer(forIncrement: 7) incrementBySeven() // returns a value of 7”
“Calling the original incrementer (incrementByTen) again continues to increment its own runningTotal variable,and does not affect the variable captured by incrementBySeven:”
再次调用原始的incrementer将会继续在他自己的runningTotal变量上增加值,但是这并不影响incrementBySeven的值。
“incrementByTen() // returns a value of 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.”
如果你给一个类的实例指派了一个闭包属性,那么这个闭包将会通过引用实例或者他的成员来捕获这个实例,你将会在闭包和他的实例中创建一个强引用循环。Swif使用引用列表打破这些强引用循环。更多信息,请看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.”
在上述例子中,incrementBySeven和incrementByTen都是常量,但是这些常量引用的闭包仍然能够将他们捕获的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 is the choice of closure that incrementByTen refers to that is 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 will refer to the same closure:”
这意味着如果你如果把一个闭包指派给了两个不同的常量或者变量,这些常量或者变量将会引用同一个闭包。
“let alsoIncrementByTen = incrementByTen alsoIncrementByTen() // returns a value of 50”