理解为什么不允许这个Swift元组赋值

时间:2022-05-06 00:31:00

The following code is fine:

以下代码没问题:

func intTest() -> Int? {
    var res : Int

    res = 5

    return res
}

There is no problem returning a non-optional Int from a method with a return type of optional Int.

从返回类型为可选Int的方法返回非可选Int是没有问题的。

Now lets see what happens when the return value is a tuple of optional values:

现在让我们看看当返回值是可选值的元组时会发生什么:

func tupleTest() -> (Int?, Int?) {
    var res : (Int, Int)

    res = (5, 5)

    return res
}

The return res line results in the error:

返回res行导致错误:

error: cannot express tuple conversion '(Int, Int)' to '(Int?, Int?)' (aka '(Optional, Optional)')

错误:无法将元组转换'(Int,Int)'表示为'(Int?,Int?)'(又名'(可选,可选)')

Why does Swift not allow this?

为什么Swift不允许这样做?

I certainly understand why this would be an error in the other direction (optional to non-optional) but why can't a tuple accept a non-optional value in the place of an optional when a non-tuple works fine?

我当然理解为什么这会是另一个方向的错误(非可选的可选)但是为什么当非元组工作正常时,元组不能在可选位置接受非可选值?

I've seen Swift tuple to Optional assignment but that doesn't cover why you can't do the assignment, it just covers how to solve it.

我已经看到Swift元组到可选作业,但这并没有涵盖为什么你不能完成作业,它只是涵盖了如何解决它。

1 个解决方案

#1


6  

The reason that's happening is because of a type mismatch. Consider the following case:

发生这种情况的原因是类型不匹配。考虑以下情况:

let myClosure: (Int) -> ()
let myOtherClosure: (Int?) -> ()

The type of myClosure is (Int) -> () while myOtherClosure is of type (Int?) -> () which makes them fundamentally different types, despite the similarity of the parameters. When Swift is looking at these two constants, it's evaluating the type as a whole, not the individual pieces. The same is happening with your tuple; it's looking at the tuple type signature as a whole unit, not breaking down the parameters and recognizing that they're non-optional versions of the same type.

myClosure的类型是(Int) - >()而myOtherClosure是类型(Int?) - >(),这使得它们基本上是不同的类型,尽管参数相似。当Swift查看这两个常量时,它会评估整个类型,而不是单个部分。你的元组也是如此;它将元组类型签名视为一个整体,而不是分解参数并认识到它们是相同类型的非可选版本。

Converting from Int to Int? works because they're the same type, one is just an optional. Going from (Int, Int) to (Int?, Int?) doesn't because the parameters of the tuple are different therefore causing the overall type to be different, hence your error.

从Int转换为Int?因为它们是同一类型而有效,一个只是可选的。从(Int,Int)到(Int?,Int?)不会因为元组的参数不同而导致整体类型不同,从而导致错误。

Taking a look at one of your examples:

看看你的一个例子:

 func tupleTest() -> (Int?, Int?) {
    let first: Int = 1
    let second: Int = 2
    let res: (Int?, Int?) = (first, second)
    return res
 }

This works because even though the values are non-optional integers, the tuple type is marked as (Int?, Int?) whereas:

这是因为即使值是非可选整数,元组类型也标记为(Int?,Int?),而:

func tupleTest() -> (Int?, Int?) {
    let first: Int = 1
    let second: Int = 2
    let res = (first, second)
    return res
}

doesn't compile because now res is of type (Int, Int). I'm not an expert on the Swift compiler but my guess is that the way the type system works is it doesn't deconstruct each individual part of a function or a tuple and recognize that the corresponding return parameter is the same type, just an optional.

不编译,因为现在res是类型(Int,Int)。我不是Swift编译器的专家,但我的猜测是类型系统的工作方式是它不解构函数或元组的每个单独部分并且识别相应的返回参数是相同的类型,只是一个可选的。

#1


6  

The reason that's happening is because of a type mismatch. Consider the following case:

发生这种情况的原因是类型不匹配。考虑以下情况:

let myClosure: (Int) -> ()
let myOtherClosure: (Int?) -> ()

The type of myClosure is (Int) -> () while myOtherClosure is of type (Int?) -> () which makes them fundamentally different types, despite the similarity of the parameters. When Swift is looking at these two constants, it's evaluating the type as a whole, not the individual pieces. The same is happening with your tuple; it's looking at the tuple type signature as a whole unit, not breaking down the parameters and recognizing that they're non-optional versions of the same type.

myClosure的类型是(Int) - >()而myOtherClosure是类型(Int?) - >(),这使得它们基本上是不同的类型,尽管参数相似。当Swift查看这两个常量时,它会评估整个类型,而不是单个部分。你的元组也是如此;它将元组类型签名视为一个整体,而不是分解参数并认识到它们是相同类型的非可选版本。

Converting from Int to Int? works because they're the same type, one is just an optional. Going from (Int, Int) to (Int?, Int?) doesn't because the parameters of the tuple are different therefore causing the overall type to be different, hence your error.

从Int转换为Int?因为它们是同一类型而有效,一个只是可选的。从(Int,Int)到(Int?,Int?)不会因为元组的参数不同而导致整体类型不同,从而导致错误。

Taking a look at one of your examples:

看看你的一个例子:

 func tupleTest() -> (Int?, Int?) {
    let first: Int = 1
    let second: Int = 2
    let res: (Int?, Int?) = (first, second)
    return res
 }

This works because even though the values are non-optional integers, the tuple type is marked as (Int?, Int?) whereas:

这是因为即使值是非可选整数,元组类型也标记为(Int?,Int?),而:

func tupleTest() -> (Int?, Int?) {
    let first: Int = 1
    let second: Int = 2
    let res = (first, second)
    return res
}

doesn't compile because now res is of type (Int, Int). I'm not an expert on the Swift compiler but my guess is that the way the type system works is it doesn't deconstruct each individual part of a function or a tuple and recognize that the corresponding return parameter is the same type, just an optional.

不编译,因为现在res是类型(Int,Int)。我不是Swift编译器的专家,但我的猜测是类型系统的工作方式是它不解构函数或元组的每个单独部分并且识别相应的返回参数是相同的类型,只是一个可选的。