Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Don't understand closures example in Swift

I'm trying to learn about swift and closures. I'm stuck on this example.

 numbers.map({
    (number: Int) -> Int in
    let result = 3 * number
    return result
 })

What is (number: Int) -> Int? Is it a function? Where is it defined? https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/GuidedTour.html#//apple_ref/doc/uid/TP40014097-CH2-ID1

What does the keyword "in" do? The docs say to use "to separate the arguments and return type from the body". I'm not sure I understand this. Why isn't "in" used to separate "let result = 3 * number" from "return result".

like image 998
user678392 Avatar asked Jan 13 '15 21:01

user678392


People also ask

What are closures in Swift with example?

Closures can be seen as blocks of code that can be passed around in your code. Blocks of code are often referenced as lambdas in other programming languages. An example from UIKit if for Adding a closure as a target to UIButton and other controls in Swift: let button = UIButton(type: .

What is the point of closures in Swift?

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. Don't worry if you aren't familiar with the concept of capturing.

What are types of closures in Swift?

There are two kinds of closures: An escaping closure is a closure that's called after the function it was passed to returns. In other words, it outlives the function it was passed to. A non-escaping closure is a closure that's called within the function it was passed into, i.e. before it returns.

How do you call closures in Swift?

Understanding closure syntax in Swift For closures, we must always write down the return type even when the closure doesn't return anything. Instead of -> Void or "returns Void ", this type specifies -> () or "returns empty tuple". In Swift, Void is a type alias for an empty tuple.


2 Answers

A closure is just a function with the parameters moved inside the brackets, with the keyword in to separate the parameters from the function body. The two following examples define equivalent functions:

func myFunc(number: Int) -> Int {
    let result = 3 * number
    return result
}

let myClosure = { (number: Int) -> Int in
    let result = 3 * number
    return result
}

You can actually call them both in exactly the same way:

let x = myFunc(2)       // x == 6
let y = myClosure(2)    // y == 6

Notice how the second example is exactly the same as the first, only in the first example, the parameters (number: Int) -> Int are outside the brackets, and in the second example the parameters are inside the brackets, followed by the keyword in.

map works by taking an array (numbers, in your example) and creating a new array that is the result of applying the closure function to each element in numbers. So if numbers is [1, 2, 3], the example above will start with 1. It will apply the closure function which will produce a 3 (cuz all it does is multiply the element from the first array by 3). It does that for each element in numbers, until it has produced a new array, [3, 6, 9].

If you wanted to, you could call map using the names of either the above function or the above closure, or by writing it out explicitly inside of map. All of the below examples are totally equivalent:

let numbers = [1, 2, 3]

// Example 1
let times3 = numbers.map(myFunc)        // times3 == [3, 6, 9]

// Example 2
let timesThree = numbers.map(myClosure) // timesThree == [3, 6, 9]

// Example 3
let xThree = numbers.map({ (number: Int) -> Int in
    let result = 3 * number
    return result                       // xThree == [3, 6, 9]
})

Note that Example 3 is the same as Example 2, only in Example 3 the closure is spelled out explicitly inside of map, whereas in Example 2 the closure has been assigned to a constant called myClosure, and the constant has been supplied to map.

Hope this helps - closures are fun, but confusing.

like image 104
Aaron Rasmussen Avatar answered Sep 20 '22 23:09

Aaron Rasmussen


The function you're calling takes a closure as its parameter:

numbers.map({...})

The closure provided to the function is expected to receive a parameter when it is executed by the function you called. This parameter is defined in your closure:

  (number: Int) -> Int in

You may now use the parameter in the contents of the closure

  let result = 3 * number
  return result
like image 34
Ian MacDonald Avatar answered Sep 18 '22 23:09

Ian MacDonald