Swift LiteralConvertible没有在返回类型中推断

时间:2015-12-18 01:38:49

标签: swift

我90%肯定这是预期的行为,但在这种情况下,我只是想接受教育!

在我的项目中,我已经定义了一个温度结构,符合IntegerLiteralConvertible协议:

struct Temperature {
    var kelvin: Int
    var celcius: Int { get { ... } }
    var fahrenheit: Int { get { ... } }
}

extension Temperature: IntegerLiteralConvertible {
    init(integerLiteral value: IntegerLiteralType) {
        kelvin = value
    }
}

现在一切正常,因为我在创建温度实例时会有所期待:

let absoluteZero: Temperature = 0 

但是如果我在定义的函数中返回Int以返回Temperature,即

func randomTemperature() -> Temperature {
    return random()
}

我将收到错误消息:"无法转换类型' Int'的返回表达式返回类型'温度'

直观地说,我希望从Temperature推断返回的类型Int,因此IntegerLiteralConvertible。

在文档中挖掘一下(或现在开源代码:D!),我发现Int结构符合继承自IntegerLiteralConvertible的SignedNumberType。我怀疑问题的答案与此有关。

那么,为什么?

提前致谢! (在此期间我会继续挖掘)

2 个答案:

答案 0 :(得分:2)

在上述评论中进行了一些讨论之后,我意识到你想要问的是:

  • 鉴于我的struct的上下文包括它的扩展名,为什么当我尝试将randomTemperature() -> Temperature value属性作为返回类型发送时int方法失败?

在代码中:

func randomTemperature() -> Temperature {
    let anyInt = 1
    return anyInt
        // Error: "Cannot convert return expression of 
        // type 'Int' to return type 'Temperature'
}

简短的回答是:你不能将'Int'类型转换为返回类型Temperature'(作为错误状态)。你问,你的初始化器怎么样? Temperature: IntegerLiteralConvertible初始化函数init(integerLiteral value: IntegerLiteralType)仅适用于文字IntegerLiteralType),整数不是文字。

如需更全面的答案,请参阅下文。

来自Apple`s documentation on literals,它说

  

文字是类型值的源代码表示,例如   作为数字或字符串。

     

...

     

文字本身没有类型。相反,文字被解析为具有无限精度和Swift的类型推断   试图推断文字的类型。

     

...

     

为文字值指定类型注释时,   注释的类型必须是可以从中实例化的类型   字面值。也就是说,类型必须符合其中之一   遵循Swift标准库协议:   整数文字的 IntegerLiteralConvertible ......

来自Apple关于IntegerLiteralConvertible协议的文档:

  

可以使用整数文字初始化符合类型。

好的,所以字面上永远不会有自己的类型。这样可以解决问题。

Temperature结构中考虑Double类型,这种类型也符合IntegerLiteralConvertible

对于Double,我们有:

func someDouble() -> Double {
    return 1 // This is ok, "1" here is a literal, and the return
             // of type Double can be initialised via the literal
}

func someDoubleTrouble() -> Double {
    let anyInt = 1
    return anyInt // Error! anyInt is not a literal, but an Int type,
                  // and return typ expects Double (or literal).
}

// The same applies for these
var someInt = 1
var anotherDouble: Double = 1 // ok, as above, literal
var anotherDoubleTrouble: Double = someInt // Error!

完全相同适用于您的Temperature结构类型。

func someTemperature() -> Temperature {
    return 1 // Ok
}

func someTroubledTemperature() -> Temperature {
    let myInt = 1
    return myInt // Error!
}

// The same applies for these
var someInt = 1
var anotherTemperature: Temperature = 1 // ok, as above, literal
var anotherTroubledTemperature: Temperature = someInt // Error!

答案 1 :(得分:1)

看来我从根本上误解了Swift中的类型系统。 IntegerLiteralConvertible代表Temperature,其他'LiteralConvertible'类型对称:

  

“符合类型可以用整数文字初始化。”

编程中的文字通常是源代码中定义的常量。直接从documentation

  

“文字是类型值的源代码表示,例如数字或字符串。”

因此,我现在知道为什么我的Int类型不能用Int初始化,而不是整数文字,IntegerLiteralConvertible只是一个结构本身符合{{1}}协议。似乎“可转换性”不是双向发生的(或者至少不是由语法分析器动态推断的)。