Swift无法推断函数的返回类型,其参数是闭包,并且返回类型是从闭包的返回类型推导出来的.
鉴于此通用类:
class Bar<T> {
init(_ v:T) {}
func wrap<R>(f:()->R) -> Bar<R> {
return Bar<R>(f())
}
func wrap(f:()->()) -> () {
f()
}
}
Run Code Online (Sandbox Code Playgroud)
wrap一旦将Closure作为返回的参数(),并且另一次将Closure作为参数返回指定为R函数的类型参数()的类型,该函数被重载.
在下面的代码片段中,很明显Closure作为参数传递给函数的返回类型wrap是String:
var bar :Bar<Int> = Bar<Int>(0)
let b0 = bar.wrap {
return ""
}
Run Code Online (Sandbox Code Playgroud)
恕我直言,编译器现在应该能够推断出类型的返回wrap类型Bar<String>,因此应该能够相应地推断出常量的类型b0.
编译器(从beta 3开始)发出以下错误:
main.swift:53:16: error: type '()' does not conform to protocol 'StringLiteralConvertible'
return ""
^
main.swift:51:9: warning: constant 'b0' inferred to have type '()', which may be unexpected
let b0 = bar.wrap {
^
main.swift:51:9: note: add an explicit type annotation to silence this warning
let b0 = bar.wrap {
^
: ()
Run Code Online (Sandbox Code Playgroud)
这个解决方法中的任何一个都可以解决问题:
let b1 = bar.wrap {
() -> String in
return ""
}
let b2:Bar<String> = bar.wrap {
return ""
}
Run Code Online (Sandbox Code Playgroud)
编辑: 添加安东尼奥的答案作为另一个正确编译的版本:
let b0 = bar.wrap { "" }
Run Code Online (Sandbox Code Playgroud)
问题是:
是否有令人信服的理由让编译器无法在失败的示例中推断返回类型,假设它按指定的方式工作?
再次,请考虑这个:
works: let b0 = bar.wrap { 0 }
fails: let b0 = bar.wrap { return 0 }
Run Code Online (Sandbox Code Playgroud)
或者,这可能是beta状态编译器的不完整或不正确实现的影响?
注意:请不要在此陈述您的意见,只有明确的事实 - 如果有的话.;)
也许你正在寻找的是单个表达式闭包的隐式返回:
let b0 = bar.wrap { "" }
Run Code Online (Sandbox Code Playgroud)
附录
对于一种方法而不是另一种方法,可能有很多话要说.本书没有提到使用just return和value 的快捷方式.但是在解释泛型类型时可行
let b2:Bar<String> = bar.wrap { return "" }
Run Code Online (Sandbox Code Playgroud)
另一方面,在快速书中的Inferring Type from Context段中,当谈到类型推断时,没有提到泛型,所以如果在这种情况下结合泛型类型时类型推断不起作用我也不会感到惊讶.
保持阅读书籍:
此参数需要类型(String,String) - > Bool的函数.这意味着String,String和Bool类型不需要作为闭包表达式定义的一部分来编写
这并不意味着(但可能)这不起作用:
() -> (T)
Run Code Online (Sandbox Code Playgroud)
其中T是泛型类型.
那就是说,我想是的
let b0 = bar.wrap { return "" }
Run Code Online (Sandbox Code Playgroud)
不起作用,因为等式中涉及泛型类型.以下是我的意见,但无论如何你应该阅读它.这可能是这样的:
let b0 = bar.wrap { "" }
Run Code Online (Sandbox Code Playgroud)
有效,但不应该.意味着它有效,但它是一个错误,它应该产生编译器错误.这有任何意义吗?