-1

In "Functions and Closures" section of "The Swift Programming Language", it says "When a closure’s type is already known, such as the callback for a delegate, you can omit the type of its parameters, its return type, or both. Single statement closures implicitly return the value of their only statement."

numbers.map({ number in 3 * number })

How does it know the argument passed in is called number?

Is the following code correct in terms of how map may be implementing it?

e.g.

func map(callback:(number:Int) -> Int) {

}
Boon
  • 40,656
  • 60
  • 209
  • 315
  • I am not sure if I understand your question after the edit. I have updated the answer with some information, perhaps it helps ... – Martin R Jun 15 '14 at 16:54
  • Hi Martin, I am trying to figure out what the map function declaration looks like. That is, if I want to create a function that can take a closure like the above, how should I define that? – Boon Jun 15 '14 at 17:06
  • I have added some example for functions taking a closure as an argument. Is that what you are looking for? – Martin R Jun 20 '14 at 07:36
  • @Boon cmd-clicking any function will bring you to it's declaration (either it's source code, if it's a class of your own; or a header, if it's an implementation by Apple). – vrwim Apr 30 '15 at 17:28

1 Answers1

2

A closure expression generally has the form

{ (param_1 : type_1, ..., param_n : type_n ) -> return_type in
    statements
}

When the closure type is known, you can omit the parameter types, the return type and also the parentheses around the parameters:

{ param_1, ..., param_n in
    statements
}

So to answer your question: The in keyword separates the parameters from the statements, therefore in your example, number is the (only) parameter.

Note that only (instance or class) methods use external (named) parameters, but (normal) functions and closures do not. So it makes no difference if you write

let clo = { number in 3 * number }
let foo = clo(1) // foo = 3

or

let clo = { x in 3 * x }
let foo = clo(1) // foo = 3

and

numbers.map(clo)

applies the closure to each element of the array and returns an array of the return values.

An implementation of map could look like this (I took and modified the code from https://stackoverflow.com/a/24028208/1187415):

extension Array {
    func myMap<U>(transform: (T) -> U) -> U[] {
        var result = U[]() // start with empty result array
        for item in self { // iterate over all items of the array
            let tmp = transform(item); // map this element ...
            result.append(tmp) // ... and append the mapped element to the result array
        }
        return result
    }
}

myMap is an instance method that takes one argument of type (T) -> U and applies it to all elements of the array itself.

A simpler example for a function (without generics) taking an integer array and a closure as arguments would be

func myMapp(array: Int[], transform:(Int)->Int) -> Int[]
{
    var result = Int[]() 
    for item in array { 
        let tmp = transform(item);
        result.append(tmp)
    }
    return result
}

Then you can do

let numbers = [1, 2, 3]
let mapped2 = myMapp(numbers, { (number) in 3 * number })
Community
  • 1
  • 1
Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382