我有一个看似合法的函数将数组转换为Dictionary:
func arrayToDictionary<Key : Hashable, Value>
  (source: Array<Value>, key: Value -> Key) -> Dictionary<Key, Value> {
   var dictionary = Dictionary<Key, Value>()
   for element in source {
     let key = key(element)
     dictionary[key] = element
   }
   return dictionary
}
现在,当我尝试调用它时:
let dict = arrayToDictionary([1, 2, 3], { val in return val })
我收到一个错误 - 无法转换表达式的类型'($ T6,(($ T9) - >($ T9) - > $ T8) - >(($ T9) - > $ T8) - > $ T8)'到类型'Hashable'
奇怪的是,如果我使用隐式回报:
let dict = arrayToDictionary([1, 2, 3], { val in val })
或速记:
let dict = arrayToDictionary([1, 2, 3], { $0 })
它工作得很好.为什么?
这个问题只能由苹果的编译器工程师真正回答,并且根据上述评论者,它可以/应该被视为一个错误,但这绝对是他们的速记语法中的一个漏洞。对于此类问题,我通过在开发论坛上发帖得到了很好的结果。
但简单的规则是,每当您有多行/需要使用关键字时return,您必须显式定义返回类型或所捕获值的类型。这一限制可能是由于以下事实:在紧凑/简并的情况下,保证只有一个退出点 - val in val,而当您使用return关键字时,可能有多个返回点。在后一种情况下,您可能会在一行返回 Int return 1,并nil在另一行返回。在这种情况下,让编译器抱怨以明确假设是合理的。简而言之,这需要在编译器中进行更复杂的类型推断,而他们可能还没有做到这一点。
所以,TL;DR,我同意将其报告为错误的建议,同时指定闭包的返回类型。正如您所说,重点仍然是编译器有足够的上下文来推断正确的类型。
请注意,除了您的示例之外,这些情况也适用:
// inferring var dict as a context for lines below
var dict = arrayToDictionary([1, 2, 3], { val in val })
// dict is already defined, so this works:
dict = arrayToDictionary([1, 2, 3], { val in return val })
// explicit final type, compiler infers backwards
let d2:Dictionary<Int, Int> = arrayToDictionary([1, 2, 3], { val in val })
// explicit return type, compiler infers "forewards"
let d3 = arrayToDictionary([1, 2, 3], { val -> Int in return val })
| 归档时间: | 
 | 
| 查看次数: | 4293 次 | 
| 最近记录: |