编译器无法推断返回类型 [英] Compiler cannot infer return type

查看:70
本文介绍了编译器无法推断返回类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Swift无法推断函数的返回类型,它的参数是一个闭包,返回类型是从闭包的返回类型推导出来的。



给定这个泛型类:

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

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

函数 wrap 被重载,一旦以Closure为参数返回(),另一次以Closure为参数返回一个为该函数指定的类型类型( R )。



在下面的代码片段中,它似乎很明显,作为参数传递给函数 wrap 的返回类型是一个 String

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

let b0 = bar.wrap {
return
}

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



编译器(从beta 3开始)发出以下错误:

  main.swift:53:16:错误:类型'()'不符合协议'StringLiteralConvertible'
返回
^
main.swift:51:9:警告:常量'b0'被推断为类型' ()',这可能是意想不到的
让b0 = bar.wrap {
^
main.swift:51:9:注意:添加一个明确的类型注解来消除这个警告
让b0 = bar.wrap {
^
:()

解决这个问题:

  let b1 = bar.wrap {
() - >
中的字符串返回
}
让b2:Bar< String> = bar.wrap {
return
}

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

  let b0 = bar.wrap {} 

问题是:

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



请再次考虑一下:

 工作原理:let b0 = bar.wrap {0} 
失败:let b0 = bar.wrap {return 0}

或者,这可能是测试版状态不完整或不正确实施的结果编译器?



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

解决方案

可能你正在寻找的是单表达式闭包的隐式返回:

 让b0 = bar.wrap {} 

附录



对于一种方法而非另一种方法,可能有很多说法。
本书不提及使用 return 和一个值的快捷方式。但是,当阐明泛型时,这是有效的。

  let b2:Bar< String> = bar.wrap {return} 

另一方面,在推断类型从快速书的上下文一节中,当谈论类型推断时,没有提及泛型,因此如果在此情况下将泛型类型与类型推断结合使用时,我不会感到惊讶。



保持阅读书籍:


这个参数需要一个类型为(String,String) - >布尔。这意味着String,String和Bool类型不需要被编写为闭包表达式定义的一部分。


t意味着(但它可能),这将无法正常工作:

 () - > (T)

其中 T 是一个通用的

这就是说,我认为

  let b0 = bar.wrap {return} 

不起作用,因为这里有一个泛型类型。 以下是我的看法,但您仍然应该阅读它。这可能是这样的:

  let b0 = bar.wrap {} 

可以工作,但不应该。这意味着它的工作,但它是一个错误,它应该产生一个编译器错误。这是否有意义?


Swift is unable to infer the return type of a function, whose parameter is a closure, and where the return type is deduced from the closure´s return type.

Given this generic class:

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

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

The function wrap is overloaded, once taking a Closure as parameter which returns (), and another time taking a Closure as parameter which returns a type specified as a type parameter (R) for the function.

In the following snippet, it seems obvious that the return type of the Closure passed as an argument to the function wrap is a String:

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

let b0 = bar.wrap {
    return ""
}

IMHO, the compiler should now be able to deduce the return type of wrap as type Bar<String>, and thus should be able to infer the type of the constant b0 accordingly.

The compiler (as of beta 3) issues the following errors:

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 {
    ^
      : ()

Either of this workaround would fix the issue:

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

Edit: added Antonio's answer as another version which compiles correctly:

let b0 = bar.wrap { "" }

The question is:

Is there a compelling reason for the compiler not being able to infer the return type in the failing examples, assuming it is working as specified?

Again, please consider this:

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

Or, is this possibly the effect of an incomplete or incorrect implementation of a beta status compiler?

Note: Please, do not state your opinions here, only clear facts - if any. ;)

解决方案

Maybe what you're looking for is the implicit return from single expression closure:

let b0 = bar.wrap { "" }

Addendum

There might be a lot to say for one method to work and not the other. The book doesn't make any mention of a shortcut using just return and a value. But that works when expliciting the generic type

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

On the other hand, in the Inferring Type from Context paragraph of the swift book, when talking about type inference there's no mention of generics, so I wouldn't be surprised if type inference doesn't work when combined with generic types in this case.

Keeping reading book:

This parameter is expecting a function of type (String, String) -> Bool. This means that the String, String, and Bool types do not need to be written as part of the closure expression’s definition

That doesn't mean (but it could) that this won't work:

() -> (T)

where T is a generic type.

That said, I think that

let b0 = bar.wrap { return "" }

doesn't work because there's a generic type involved in the equation. What follows is my opinion, but you should read it anyway. It's possible that this:

let b0 = bar.wrap { "" }

works but it shouldn't. Meaning that it works, but it's a bug, it should produce a compiler error. Does that make any sense?

这篇关于编译器无法推断返回类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆