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. Swift handles all of the memory management of capturing for you.

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.

The Sorted Method

기본 라이브러리에 sorted()라는 함수가 있는데 어떻게 분류하는지에 대한 부분을 함수형태의 argument로 받아들인다. closure의 사용예를 위해 sorted()를 사용했다.

일반 함수를 이용한 방법

func backward(_ s1: String, _ s2: String) -> Bool {
   return s1 > s2
}
var reversedNames = names.sorted(by: backward)
// reversedNames is equal to [“Ewa”, “Daniella”, “Chris”, “Barry”, “Alex”]

Closure Expression Syntax

{ (parameters) -> return type in
   statements
}

closure를 이용한 방법

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

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 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:

reversedNames = names.sorted(by: { 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 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.

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:

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 is no ambiguity, and the return keyword can be omitted.

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.

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:

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

Here, $0 and $1 refer to the closure’s first and second String arguments.

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:

reversedNames = names.sorted(by: >)

For more about operator method, 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. A trailing closure is written after the function call’s parentheses, even though it is still an argument to the function. When you use the trailing closure syntax, you don’t write the argument label for the closure as part of the function call.

func someFunctionThatTakesAClosure(closure: () -> Void) {
   // function body goes here
}
// Here’s how you call this function without using a trailing closure(일반방법)
someFunctionThatTakesAClosure(closure: {
   // closure’s body goes here
})

——————————————————————————————

// Here’s how you call this function with a trailing closure instead:
someFunctionThatTakesAClosure() {
   // trailing closure’s body goes here

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:

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

If a closure expression is provided as the function or method’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 or method’s name when you call the function:

reversedNames = names.sorted { $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 { (number) -> String in
   var number = number
   var output = “”
   repeat {
       output = digitNames[number % 10]! + output
       number /= 10
   } while number > 0
   return output
}
// strings is inferred to be of type [String]
// its value is [“OneSix”, “FiveEight”, “FiveOneZero”]

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.

// ()->int meant reture type is function type

func makeIncrementer(forIncrement amount: Int) -> () -> Int {
   var runningTotal = 0
   func incrementer() -> Int {
       runningTotal += amount
       return runningTotal
   }

// return closure
   return incrementer
}

func incrementer() -> Int {
   runningTotal += amount
   return runningTotal
}

함수내에서 만들어진 nested 함수는 nesting 함수의 변수에 접근 가능하고 

이는 마치 python의 class variable 처럼 계속 남아 유지 하게 되며 nested 함수에서 수시로 접근 가능하다.

let incrementByTen = makeIncrementer(forIncrement: 10)

incrementByTen()
// returns a value of 10
incrementByTen()
// returns a value of 20
incrementByTen()
// returns a value of 30

// new nested function is made and will be used differently from above

let incrementBySeven = makeIncrementer(forIncrement: 7)
incrementBySeven()
// returns a value of 7

incrementByTen()
// returns a value of 40

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.

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.

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

Escaping Closures

참고자료 : ref) https://www.andrewcbancroft.com/2017/04/26/what-in-the-world-is-an-escaping-closure-in-swift/

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.

One way that a closure can escape is by being stored in a variable that is 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:

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

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.

Marking a closure with @escaping means you have to refer to self explicitly within the closure. For example, in the code below, the closure passed to someFunctionWithEscapingClosure(_:) is an escaping closure, which means it needs to refer to self explicitly. In contrast, the closure passed to someFunctionWithNonescapingClosure(_:) is a nonescaping closure, which means it can refer to self implicitly.

func someFunctionWithNonescapingClosure(closure: () -> Void) {
   closure()
}
class SomeClass {
   var x = 10
   func doSomething() {
       someFunctionWithEscapingClosure { self.x = 100 }
       someFunctionWithNonescapingClosure { x = 200 }
   }
}
let instance = SomeClass()
instance.doSomething()
print(instance.x)
// Prints “200”
completionHandlers.first?()
print(instance.x)
// Prints “100″

Autoclosures

An autoclosure is a closure that is 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 messageparameters; its condition parameter is evaluated only in debug builds and its message parameter is evaluated only if condition is false.

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.

var customersInLine = ["Chris”, “Alex”, “Ewa”, “Barry”, “Daniella”]
print(customersInLine.count)
// Prints “5”
let customerProvider = { customersInLine.remove(at: 0) }
print(customersInLine.count)
// Prints “5”
print(“Now serving (customerProvider())!”)
// Prints “Now serving Chris!”
print(customersInLine.count)
// 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 is not String but () -> String—a function with no parameters that returns a string.

You get the same behavior of delayed evaluation when you pass a closure as an argument to a function.

// customersInLine is [“Alex”, “Ewa”, “Barry”, “Daniella”]
func serve(customer customerProvider: () -> String) {
   print(“Now serving (customerProvider())!”)
}
serve(customer: { customersInLine.remove(at: 0) } )
// 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.

// customersInLine is [“Ewa”, “Barry”, “Daniella”]
func serve(customer customerProvider: @autoclosure () -> String) {
   print(“Now serving (customerProvider())!”)
}
serve(customer: customersInLine.remove(at: 0))
// 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 is allowed to escape, use both the @autoclosure and @escaping attributes. The @escaping attribute is described above in Escaping Closures.

// customersInLine is [“Barry”, “Daniella”]
var customerProviders: [() -> String] = []
func collectCustomerProviders(_ customerProvider: @autoclosure @escaping () -> String) {
   customerProviders.append(customerProvider)
}
collectCustomerProviders(customersInLine.remove(at: 0))
collectCustomerProviders(customersInLine.remove(at: 0))
print(“Collected (customerProviders.count) closures.”)
// Prints “Collected 2 closures.”
for customerProvider in customerProviders {
   print(“Now serving (customerProvider())!”)
}
// Prints “Now serving Barry!”
// 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.

optional ,nil, 

If Statements and Forced Unwrapping,

Optional Binding

ref) https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/TheBasics.html#//apple_ref/doc/uid/TP40014097-CH5-ID309

Early Exit

ref) https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/ControlFlow.html#//apple_ref/doc/uid/TP40014097-CH9-ID120

Optional Tuple Return Types  ref) https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Functions.html

Functions

Swift’s unified function syntax is flexible enough to express anything from a function with no parameter names to method with names and argument labels for each parameter. Parameters can provide default values.

Every function in Swift has a type, consisting of the function’s parameter types and return type. Functions can also be written within other functions to encapsulate useful functionality within a nested function scope.

Defining and Calling Functions

When you define a function, you can optionally define one or more named, typed values that the function takes as input, known as parameters. You can also optionally define a type of value that the function will pass back as output when it is done, known as its return type.

To use a function, you “call” that function with its name and pass it input values. A function’s arguments must always be provided in the same order as the function’s parameter list.

func greet(person: String) -> String {
   let greeting = “Hello, ” + person + “!”
   return greeting
}

NOTE

The print(_:separator:terminator:) function doesn’t have a label for its first argument, and its other arguments are optional because they have a default value.

Function Parameters and Return Values

Functions Without Parameters

func sayHelloWorld() -> String {
   return “hello, world”
}
print(sayHelloWorld())
// Prints “hello, world”

Functions With Multiple Parameters

func greet(person: String, alreadyGreeted: Bool) -> String {
   if alreadyGreeted {
       return greetAgain(person: person)
   } else {
       return greet(person: person)
   }
}
print(greet(person: “Tim”, alreadyGreeted: true))
// Prints “Hello again, Tim!”

greet(person:alreadyGreeted:) 함수와 

greet(person:) 는 이름은 같으나 받아들이는 parameters 가 다르므로 다른 함수이다.

Functions Without Return Values

func greet(person: String) {
   print(“Hello, (person)!”)
}
greet(person: “Dave”)
// Prints “Hello, Dave!”

Because it does not need to return a value, the function’s definition does not include the return arrow (->) or a return type.

NOTE

Strictly speaking, this version of the greet(person:) function does still return a value, even though no return value is defined. Functions without a defined return type return a special value of type Void. This is simply an empty tuple, which is written as ()

.The return value of a function can be ignored when it is called:

func printAndCount(string: String) -> Int {
   print(string)
   return string.count
}
func printWithoutCounting(string: String) {
   let _ = printAndCount(string: string)
}
printAndCount(string: “hello, world”)
// prints “hello, world” and returns a value of 12
printWithoutCounting(string: “hello, world”)
// prints “hello, world” but does not return a value

NOTE

Return values can be ignored, but a function that says it will return a value must always do so. A function with a defined return type cannot allow control to fall out of the bottom of the function without returning a value, and attempting to do so will result in a compile-time error.

Functions with Multiple Return Values

func minMax(array: [Int]) -> (min: Int, max: Int) {
   var currentMin = array[0]
   var currentMax = array[0]
   for value in array[1..<array.count] {
       if value < currentMin {
           currentMin = value
       } else if value > currentMax {
           currentMax = value
       }
   }
   return (currentMin, currentMax)
}

let bounds = minMax(array: [8, -6, 2, 109, 3, 71])
print(“min is (bounds.min) and max is (bounds.max)”)
// Prints “min is -6 and max is 109”

Note 

that the tuple’s members do not need to be named at the point that the tuple is returned from the function, because their names are already specified as part of the function’s return type.

Optional Tuple Return Types

you can use an optional tuple return type to reflect the fact that the entire tuple can be nil. You write an optional tuple return type by placing a question mark after the tuple type’s closing parenthesis, such as (Int, Int)?or (String, Int, Bool)?.

NOTE

An optional tuple type such as (Int, Int)? is different from a tuple that contains optional types such as (Int?, Int?). With an optional tuple type, the entire tuple is optional, not just each individual value within the tuple.

func minMax(array: [Int]) -> (min: Int, max: Int)? {
   if array.isEmpty { return nil }
   var currentMin = array[0]
   var currentMax = array[0]
   for value in array[1..<array.count] {
       if value < currentMin {
           currentMin = value
       } else if value > currentMax {
           currentMax = value
       }
   }
   return (currentMin, currentMax)
}

You can use optional binding to check whether this version of the minMax(array:) function returns an actual tuple value or nil:

if let bounds = minMax(array: [8, -6, 2, 109, 3, 71]) {
   print(“min is (bounds.min) and max is (bounds.max)”)
}
// Prints “min is -6 and max is 109”

Function Argument Labels and Parameter Names

Each function parameter has both an argument label and a parameter name. The argument label is used when calling the function; each argument is written in the function call with its argument label before it. The parameter name is used in the implementation of the function. By default, parameters use their parameter name as their argument label.

func someFunction(firstParameterName: Int, secondParameterName: Int) {
   // In the function body, firstParameterName and secondParameterName
   // refer to the argument values for the first and second parameters.
}
someFunction(firstParameterName: 1, secondParameterName: 2)

You write an argument label before the parameter name, separated by a space:

func someFunction(argumentLabel parameterName: Int) {
   // In the function body, parameterName refers to the argument value
   // for that parameter.
}

argument label 과  parameter name 를 구분해서 사용하는 예시

func greet(person: String, from hometown: String) -> String {
   return “Hello (person)!  Glad you could visit from (hometown).”
}
print(greet(person: “Bill”, from: “Cupertino”))
// Prints “Hello Bill!  Glad you could visit from Cupertino.”

Omitting Argument Labels

If you don’t want an argument label for a parameter, write an underscore (_) instead of an explicit argument label for that parameter.

func someFunction(_ firstParameterName: Int, secondParameterName: Int) {
   // In the function body, firstParameterName and secondParameterName
   // refer to the argument values for the first and second parameters.
}
someFunction(1, secondParameterName: 2)

Default Parameter Values

func someFunction(parameterWithoutDefault: Int, parameterWithDefault: Int = 12) {
   // If you omit the second argument when calling this function, then
   // the value of parameterWithDefault is 12 inside the function body.
}
someFunction(parameterWithoutDefault: 3, parameterWithDefault: 6) // parameterWithDefault is 6
someFunction(parameterWithoutDefault: 4) // parameterWithDefault is 12

Variadic Parameters

A variadic parameter accepts zero or more values of a specified type. You use a variadic parameter to specify that the parameter can be passed a varying number of input values when the function is called. Write variadic parameters by inserting three period characters (...) after the parameter’s type name.

The values passed to a variadic parameter are made available within the function’s body as an array of the appropriate type.

func arithmeticMean(_ numbers: Double…) -> Double {
   var total: Double = 0
   for number in numbers {
       total += number
   }
   return total / Double(numbers.count)
}
arithmeticMean(1, 2, 3, 4, 5)
// returns 3.0, which is the arithmetic mean of these five numbers
arithmeticMean(3, 8.25, 18.75)
// returns 10.0, which is the arithmetic mean of these three numbers

NOTE

A function may have at most one variadic parameter.

In-Out Parameters

Function parameters are constants by default. Trying to change the value of a function parameter from within the body of that function results in a compile-time error. If you want a function to modify a parameter’s value(전달된 variable형식의 argument값을 함수내에서 처리한후 외부에서도 variable의 변화값이 유지되게 하는 경우 ), and you want those changes to persist after the function call has ended, define that parameter as an in-out parameter instead.

You write an in-out parameter by placing the inout keyword right before a parameter’s type. 

You can only pass a variable as the argument for an in-out parameter. You cannot pass a constant or a literal value as the argument, because constants and literals cannot be modified. You place an ampersand (&) directly before a variable’s name when you pass it as an argument to an in-out parameter, to indicate that it can be modified by the function.

NOTE

In-out parameters cannot have default values, and variadic parameters cannot be marked as inout.

func swapTwoInts(_ a: inout Int, _ b: inout Int) {
   let temporaryA = a
   a = b
   b = temporaryA
}

var someInt = 3
var anotherInt = 107
swapTwoInts(&someInt, &anotherInt)
print(“someInt is now (someInt), and anotherInt is now (anotherInt)”)
// Prints “someInt is now 107, and anotherInt is now 3”

NOTE

In-out parameters are not the same as returning a value from a function. The swapTwoInts example above does not define a return type or return a value, but it still modifies the values of someInt and anotherInt. In-out parameters are an alternative way for a function to have an effect outside of the scope of its function body.

Function Types

Every function has a specific function type, made up of the parameter types and the return type of the function.

func addTwoInts(_ a: Int, _ b: Int) -> Int {
   return a + b
}
func multiplyTwoInts(_ a: Int, _ b: Int) -> Int {
   return a * b
}

The type of both of these functions is (Int, Int) -> Int. This can be read as:

“A function that has two parameters, both of type Int, and that returns a value of type Int.”

Here’s another example, for a function with no parameters or return value:

func printHelloWorld() {
   print(“hello, world”)
}

The type of this function is () -> Void, or “a function that has no parameters, and returns Void.”

Using Function Types

You use function types just like any other types in Swift. For example, you can define a constant or variable to be of a function type and assign an appropriate function to that variable:

var mathFunction: (Int, Int) -> Int = addTwoInts

This can be read as:

“Define a variable called mathFunction, which has a type of ‘a function that takes two Int values, and returns an Int value.’ Set this new variable to refer to the function called addTwoInts.”

The addTwoInts(_:_:) function has the same type as the mathFunction variable, and so this assignment is allowed by Swift’s type-checker.

You can now call the assigned function with the name mathFunction:

print(“Result: (mathFunction(2, 3))”)
// Prints “Result: 5”

A different function with the same matching type can be assigned to the same variable, in the same way as for nonfunction types:

mathFunction = multiplyTwoInts
print(“Result: (mathFunction(2, 3))”)
// Prints “Result: 6”

As with any other type, you can leave it to Swift to infer the function type when you assign a function to a constant or variable:

let anotherMathFunction = addTwoInts
// anotherMathFunction is inferred to be of type (Int, Int) -> Int

Function Types as Parameter Types

You can use a function type such as (Int, Int) -> Int as a parameter type for another function. This enables you to leave some aspects of a function’s implementation for the function’s caller to provide when the function is called.

Here’s an example to print the results of the math functions from above:

func printMathResult(_ mathFunction: (Int, Int) -> Int, _ a: Int, _ b: Int) {
   print(“Result: (mathFunction(a, b))”)
}
printMathResult(addTwoInts, 3, 5)
// Prints “Result: 8”

This example defines a function called printMathResult(_:_:_:), which has three parameters. The first parameter is called mathFunction, and is of type (Int, Int) -> Int. You can pass any function of that type as the argument for this first parameter. The second and third parameters are called a and b, and are both of type Int. These are used as the two input values for the provided math function.

When printMathResult(_:_:_:) is called, it is passed the addTwoInts(_:_:) function, and the integer values 3and 5. It calls the provided function with the values 3 and 5, and prints the result of 8.

The role of printMathResult(_:_:_:) is to print the result of a call to a math function of an appropriate type. It doesn’t matter what that function’s implementation actually does—it matters only that the function is of the correct type. This enables printMathResult(_:_:_:) to hand off some of its functionality to the caller of the function in a type-safe way.

(printMathResult 라는 wrapper 함수를 만들고 함수의 타입만 맞는다면 다양한 함수와 변수를 받아드리고 가변적인 결과를 만들어 낼수 있다는 것을 보여주는 예시 )

Function Types as Return Types

You can use a function type as the return type of another function. You do this by writing a complete function type immediately after the return arrow (->) of the returning function.

The next example defines two simple functions called stepForward(_:) and stepBackward(_:). The stepForward(_:) function returns a value one more than its input value, and the stepBackward(_:) function returns a value one less than its input value. Both functions have a type of (Int) -> Int:

func stepForward(_ input: Int) -> Int {
   return input + 1
}
func stepBackward(_ input: Int) -> Int {
   return input – 1
}

Here’s a function called chooseStepFunction(backward:), whose return type is (Int) -> Int. The chooseStepFunction(backward:) function returns the stepForward(_:) function or the stepBackward(_:) function based on a Boolean parameter called backward:

func chooseStepFunction(backward: Bool) -> (Int) -> Int {
   return backward ? stepBackward : stepForward
}

You can now use chooseStepFunction(backward:) to obtain a function that will step in one direction or the other:

var currentValue = 3
let moveNearerToZero = chooseStepFunction(backward: currentValue > 0)
// moveNearerToZero now refers to the stepBackward() function

The preceding example determines whether a positive or negative step is needed to move a variable called currentValue progressively closer to zero. currentValue has an initial value of 3, which means that currentValue > 0 returns true, causing chooseStepFunction(backward:) to return the stepBackward(_:)function. A reference to the returned function is stored in a constant called moveNearerToZero.

Now that moveNearerToZero refers to the correct function, it can be used to count to zero:

print(“Counting to zero:”)
// Counting to zero:
while currentValue != 0 {
   print(“(currentValue)… ”)
   currentValue = moveNearerToZero(currentValue)
}
print(“zero!”)
// 3…
// 2…
// 1…
// zero!

(상황에 따라 리턴하는 함수가 달라지는 wrapper함수를 만드는 과정을 보여준다. )

Nested Functions

All of the functions you have encountered so far in this chapter have been examples of global functions, which are defined at a global scope. You can also define functions inside the bodies of other functions, known as nested functions.

Nested functions are hidden from the outside world by default, but can still be called and used by their enclosing function. An enclosing function can also return one of its nested functions to allow the nested function to be used in another scope.

You can rewrite the chooseStepFunction(backward:) example above to use and return nested functions:

func chooseStepFunction(backward: Bool) -> (Int) -> Int {
   func stepForward(input: Int) -> Int { return input + 1 }
   func stepBackward(input: Int) -> Int { return input – 1 }
   return backward ? stepBackward : stepForward
}
var currentValue = -4
let moveNearerToZero = chooseStepFunction(backward: currentValue > 0)
// moveNearerToZero now refers to the nested stepForward() function
while currentValue != 0 {
   print(“(currentValue)… ”)
   currentValue = moveNearerToZero(currentValue)
}
print(“zero!”)
// -4…
// -3…
// -2…
// -1…
// zero!