假设我有一个结构 AStruct:
struct AStruct {
let name: String
let value: Int
}
假设我有一个 AStruct
数组:
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)
]
现在假设我想使用 map()
从我的 AStruct
数组中创建一个整数数组。
此代码有效:
let values = array.map { $0.value }
但是如果我尝试使用 Swift 键路径语法,无论我尝试什么都会出错。示例:
let values = array.map { \.value }
我得到一个错误:
Cannot infer key path type from context; consider explicitly specifying a root type.
那我该怎么做呢?
如果我给输入一个名称和类型,我就能让它工作:
let values = array.map { (aVal: AStruct) -> Int in
return aVal.value
}
但这显然不是关键路径语法。
最佳答案
SE-0249: Key Path Expressions as Functions是针对此功能的相关 Swift Evolution 提案,并且来自该提案:
As implemented in apple/swift#19448, occurrences of
\Root.value
are implicitly converted to key path applications of{ $0[keyPath: \Root.value] }
wherever(Root) -> Value
functions are expected. For example:users.map(\.email)
Is equivalent to:
users.map { $0[keyPath: \User.email] }
<截图>
When inferring the type of a key path literal expression like
\Root.value
, the type checker will preferKeyPath<Root, Value>
or one of its subtypes, but will also allow(Root) -> Value
. If it chooses(Root) -> Value
, the compiler will generate a closure with semantics equivalent to capturing the key path and applying it to the Root argument. For example:// You write this: let f: (User) -> String = \User.email // The compiler generates something like this: let f: (User) -> String = { kp in { root in root[keyPath: kp] } }(\User.email)
换句话说:编译器识别键路径表达式当作为直接参数传入到期望函数的位置时,并注入(inject)从键路径到生成的闭包的转换。当你写作时
array.map { \.value }
您正在传递一个闭包,其主体评估 到一个关键路径,因为关键路径对编译器来说似乎是任意的(例如,它没有类型 \.value
的上下文)根除),你会得到错误。
还需要注意的是:
The implementation is limited to key path literal expressions (for now), which means the following is not allowed:
let kp = \User.email // KeyPath<User, String> users.map(kp)
我不记得此时此限制是否已解除,但如果您发现自己处于需要应用的键路径但自动转换不起作用的情况,则需要通过手动将键路径插入闭包,然后直接关闭该键路径。
关于swift - 为什么不能在 map 语句中使用键路径语法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72652593/