Imagine I have a struct AStruct:
struct AStruct {
let name: String
let value: Int
}
And imagine I have an array of AStructs:
let array: [AStruct] = [
AStruct(name: "John", value: 1),
AStruct(name: "Bob", value: 23),
AStruct(name: "Carol", value: 17),
AStruct(name: "Ted", value: 9),
AStruct(name: "Alice", value: 13),
AStruct(name: "Digby", value: 4)
]
Now imagine I want to use a map() to create an array of integers out of my array of AStructs.
This code works:
let values = array.map { $0.value }
But if I try to use Swift key path syntax I get errors no matter what I try. Example:
let values = array.map { \.value }
I get an error:
Cannot infer key path type from context; consider explicitly specifying a root type.
So how do I that?
I can get it to work if I give the input a name and type:
let values = array.map { (aVal: AStruct) -> Int in
return aVal.value
}
But that is distinctly not key path syntax.
SE-0249: Key Path Expressions as Functions is the relevant Swift Evolution proposal for this feature, and from that proposal:
<snip>
In other words: the compiler recognizes a keypath expression when passed in as a direct argument to where a function is expected, and injects a conversion from the keypath to a generated closure. When you write
you are passing in a closure whose body evaluates to a key path, and because the key path is then seemingly arbitrary to the compiler here (e.g., it has no context for what type
\.valueis rooted off of), you get the error.Also important to note is that:
I don't recall whether this restriction has been lifted at this point, but if you find yourself in a situation where you have a keypath you need to apply but automatic conversion won't work, you'll need to pass the keypath into a closure manually, and key off of that keypath directly.