10
votes

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".

3
This is also a good introduction to closures in Swift:letvargo.mooo.com/a-beginners-guide-to-closures-in-swift)Aaron Rasmussen

3 Answers

36
votes

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.

2
votes

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
0
votes

Closures are self-contained blocks of functionality that can be passed around and used in your code.

Syntax:

{(parameterName: ParameterType) -> returnType in
    //Statements
}

Practical Scenario: When user want to apply filter and want to select values which is more than 300(in this case) we can use closures to achive this.

var elements: [Int] = [Int]() //Declaring Empty array
elements = [1001, 999, 555, 786, 988, 322, 433, 128, 233, 222, 201, 276, 133]

var filteredElements = elements.map({(num: Int) -> Int? in
    return num > 300 ? num : nil
})

output:
[Optional(1001), Optional(999), Optional(555), Optional(786), Optional(988), Optional(322), Optional(433), nil, nil, nil, nil, nil, nil]

From Below code you can clearly see we are passing closure to elements.map() function.

Closure:

{(num: Int) -> Int? in
        return num > 300 ? num : nil
    }

(num:Int) is parameter. Int? is we are going to return Optional Integer Type.

After in we can write your logic.

You can read more about closure here.