In trying to understand KeyPath
I've been experimenting with this example:
let names: [String] = ["Chris", "Claire", "Finny"]
let optionalNames: [String?] = ["Chris", nil, "Claire"]
let mapped1 = names.compactMap { $0 }
let mapped2 = optionalNames.compactMap { $0 }
// let mapped3 = optionalNames.compactMap(\.self)
print(mapped1)
print(mapped2)
// print(mapped3)
This behaves just like I expect. But when I uncomment the line with let mapped3 = optionalNames.compactMap(\.self)
I get the following issues which I'm not sure how to interpret:
error: Playground.playground:6:15: error: generic parameter 'ElementOfResult' could not be inferred
let mapped3 = optionalNames.compactMap(.self)
Swift.Sequence:2:28: note: in call to function 'compactMap'
@inlinable public func compactMap<ElementOfResult>(_ transform: (Self.Element) throws -> ElementOfResult?) rethrows -> [ElementOfResult]
error: Playground.playground:6:40: error: cannot convert value of type 'WritableKeyPath<, >' to expected argument type '(String?) throws -> ElementOfResult?'
let mapped3 = optionalNames.compactMap(.self)
error: Playground.playground:6:40: error: cannot infer key path type from context; consider explicitly specifying a root type
let mapped3 = optionalNames.compactMap(.self)
My (apparently flawed) understanding of KeyPath
s would suggest that mapped2
and mapped3
should be equivalent but apparently they're not.
If I try this
struct Person {
let name: String
}
let persons = [
Person(name: "Mark"),
Person(name: "Emma"),
]
let mapped4 = persons.map { $0.name }
let mapped5 = persons.map(\.name)
print(mapped4)
print(mapped5)
I get, as expected, the following output:
["Mark", "Emma"]
["Mark", "Emma"]
But if I replace the mapped5
definition with let mapped5 = persons.map(\.self)
I get the error:
error: Playground.playground:18:23: error: no exact matches in call to instance method 'map'
let mapped5 = persons.map(.self)
Playground.playground:18:23: note: found candidate with type '((Person) throws -> ) throws -> Array<>'
let mapped5 = persons.map(.self)
It seems I'm misunderstanding what a keypath to \.self
does here but I don't know how exactly. Could somebody clarify what's going on here?