Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding shorthand closure syntax for map function in Swift

I'm trying to understand some of the short hand syntax used by the map function.

The following is the setup

    let array = [1, 2, 3]

    // these make sense
    let arr1 = array.map({String($0)})
    let arr2 = array.map{String($0)}
    let arr3 = array.map({ number in
        return String(number)
    })
    let arr4 = array.map({ (number) -> String in
        String(number)
    })

Here is where the confusion lays. In swift I can forgo the curly braces for map, but this seems like something that can't be done, for my own functions where I have a trailing closure. Some magical inference that's being made perhaps? Also why is the String initialized in this way?

    // this doesn't make sense. Foregoing the curly braces? I can't do that!!!
    let arr5 = array.map(String.init)    
    let arr6 = array.map(String())    // Compile Error: Cannot convert value of type 'String' to expected argument type '@noescape (Int) throws -> _'

This is me trying to use similar syntax as map

func crap(block:(Int)-> String) {
    print("Int to string block" + block(1));
}
// works obviously
crap{ "\($0) some garbage" }
// compile error : Anonymous closure argument not contained in a closure
crap( "\($0) some garbage" )
like image 241
Biclops Avatar asked Mar 12 '23 04:03

Biclops


1 Answers

Distinguish parentheses () from curly braces {}.

In a sense, only the parentheses version is "real", because, after all, that is what a function call requires. In the parentheses when you call map, you put a function. It may be a function reference (i.e. the name of a function):

    let arr = [1,2,3]
    func double(i:Int) -> Int {return i*2}
    let arr2 = arr.map(double)

Or it can be an anonymous function, meaning a function body in curly braces:

    let arr = [1,2,3]
    let arr2 = arr.map({$0*2})

But in that case, and that case only, you can (as a shortcut) use the "trailing closure" syntax instead:

    let arr = [1,2,3]
    let arr2 = arr.map(){$0*2}

But since map takes no other parameters, you can then also omit the parentheses — the only situation in Swift where you can call a function without parentheses:

    let arr = [1,2,3]
    let arr2 = arr.map{$0*2}
like image 192
matt Avatar answered Mar 29 '23 23:03

matt