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 init
s 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:
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
.