Any diff? .map(Int.init) vs. .map { Int($0) }

let a = ["1"]

// is there any difference between these two?
// should prefer the first form to avoid extra level of indirection?
// or the compiler can optimize to be the same if possible?
let zzzz = a.map(Int.init)       // it reads like a closure of Int.init is passing
let yyyy = a.map { Int($0) }   // here, a closure that calls the closure Int.init <== anything can be here
// for sure the compile cannot optimize out this?
let xxxx = a.map {
    // some more complicate code
    for c in $0 {
        // calculate thing
    }
}

I'm pretty sure that yyyy has an extra indirection for naive interpretation, but it should be optimized away in essentially all cases given how aggressive Swift compiler is about that.

zzzz can also be ambiguous if there are multiple matching inits with differing label. I'd prefer Int.init(_:), but that's just me.

okay. I shouldn't worry about which way is better and simply rely on optimization.

I have a case like this:

...
init(_ component: String) { ... }
init(fatalError message: String) { ... }

the compiler show error "ambiguous without more context". It seems to know .init by itself is ambiguous so the compile actually force you to choose.

You shouldn't worry too much about optimization so long as your intend is clear. Compiler tends to do a pretty good job at doing these micro optimizations.

Yup, you have .init(_:) and .init(fatalError:), both of which can be referred to as .init and are of type (String) -> X which is wholly ambiguous. That's why I use a full name to avoid ambiguity, especially with a common type like Int.

So for mutating func foo(), you can get error:

Partial application of 'mutating' method is not allowed

if you pass in the direct closure foo and must use indirect closure instead { x.foo() }.

That's a different issue. Storing mutating functions could be interpreted in two different ways. It could mean that the mutation spans the duration of the function call. It could also mean that the mutation spans lifetime of the variable. Swift (currently) is just defensive and disallow that.

So instead you storing x.foo, you store x and call x.foo.

1 Like