编译器无法推断返回类型

时间:2014-07-16 19:16:21

标签: swift generics

Swift无法推断函数的返回类型,其参数是闭包,返回类型是从闭包的返回类型中推断出来的。

鉴于这个通用类:

class Bar<T> {
    init(_ v:T) {}

    func wrap<R>(f:()->R) -> Bar<R> {
        return Bar<R>(f())
    }
    func wrap(f:()->()) -> () {
        f()
    }
}

函数wrap被重载,一旦将Closure作为参数返回(),另一次将Closure作为参数返回指定为类型参数的类型(R )为功能。

在下面的代码片段中,显然将作为参数传递给函数wrap的Closure的返回类型是String

var bar :Bar<Int> = Bar<Int>(0)

let b0 = bar.wrap {
    return ""
}

恕我直言,编译器现在应该能够将wrap的返回类型推断为类型Bar<String>,因此应该能够相应地推断常量b0的类型。 / p>

编译器(从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 {
    ^
      : ()

这种解决方法都可以解决问题:

let b1 = bar.wrap {
    () -> String in
    return ""
}
let b2:Bar<String> = bar.wrap {
    return ""
}

编辑将Antonio的答案添加为另一个正确编译的版本:

let b0 = bar.wrap { "" }

问题是:

是否有令人信服的理由让编译器无法在失败的示例中推断出返回类型,假设它按指定的方式工作?

再次,请考虑一下:

works: let b0 = bar.wrap { 0 }
fails: let b0 = bar.wrap { return 0 }

或者,这可能是beta状态编译器不完整或不正确实现的影响吗?

注意:请不要在此陈述您的意见,只有明确的事实 - 如果有的话。 ;)

1 个答案:

答案 0 :(得分:5)

也许您正在寻找的是单表达式闭包的隐式返回:

let b0 = bar.wrap { "" }

<强>附录

对于一种方法而言,可能有很多话要说而不是另一种方法。 这本书没有提到仅使用return和值的快捷方式。但是在解释泛型类型

时可行
let b2:Bar<String> = bar.wrap { return "" }

另一方面,在快速书的Inferring Type from Context段中,当谈到类型推断时,没有提到泛型,所以如果类型推断没有&#我就不会感到惊讶39;在这种情况下与泛型类型结合使用时。

保持阅读书籍:

  

此参数需要类型(String,String)的函数 - &gt;布尔。这意味着String,String和Bool类型不需要作为闭包表达式定义的一部分来编写

这并不意味着(但可能)这不会起作用:

() -> (T)

其中T是泛型类型。

那就是说,我认为

let b0 = bar.wrap { return "" }

不起作用,因为方程中涉及的泛型类型。 以下是我的意见,但无论如何你应该阅读它。这可能是这样的:

let b0 = bar.wrap { "" }

有效,但不应该。意味着它有效,但它是一个错误,它应该产生编译器错误。这有什么意义吗?

相关问题