gpt4 book ai didi

ios - if let 在显式指定类型时表现得很奇怪

转载 作者:搜寻专家 更新时间:2023-10-30 22:09:06 25 4
gpt4 key购买 nike

假设我们有:

let a:Int? = nil

// block not executed - unwapping done, type is inferred
if let unwrapped_a = a {
println(unwrapped_a)
}

// block not executed - unwrapping done, type is specified
if let unwrapped_a:Int = a {
println(unwrapped_a)
}

// block gets executed - unwrapping not done, new local constant + assignment is done instead?
if let not_unwrapped_a:Int? = a {
println(not_unwrapped_a)
}

那么我是否应该假设 Swift 在第一种情况下进行解包,而在第二种情况下进行赋值?

这种语法是不是太接近了,不会造成混淆?我的意思是,是的,编译器会警告您在使用 not_unwrapped_a 时您正在使用可选类型,但仍然如此。

更新:

所以在 Airspeed Velocity 的回答之后我发现了另一个(但实际上是相同的)奇怪的案例:

if let not_unwrapped_a:Int???? = a {
println(not_unwrapped_a)
}

a 将被默默地包裹在 Int????? 中。所以它将是 Int?????? 的类型(五)——因为 a 已经是可选的。然后它会被解包一次。

最佳答案

情况 1 和情况 2 是相同的——它们都是将 a 的内容赋值给一个新变量。唯一的区别是您让 Swift 在选项 1 中推断 unwrapped_a 的类型,而您在选项 2 中手动给出类型。您需要执行选项 2 的主要原因是如果源值不明确——例如,如果它是一个可以返回多种类型的重载函数。

案例 3 很有趣。

只要你有一个值,如果它有助于类型匹配和代码编译,Swift 总是愿意默默地将它升级为可选的包装值。 Swift 类型的自动升级是相当罕见的(例如,它不会隐式地将 Int16 升级到 Int32),但可选值是一个异常(exception)。

这意味着您可以在任何需要可选的地方传递值,而不必费心包装它:

func f(maybe: Int?) { ... }

let i = 1

// you can just pass a straight value:
f(i)

// Swift will turn this into this:
f(Optional(i))

因此,在您的最后一个示例中,您已经告诉 Swift 您希望 not_unwrapped_a 成为一个 Int?。但它是 let 的一部分,需要 a 在分配给它之前解包。

面对这种情况,Swift 让它工作的唯一方法是将 a 隐式包装在另一个可选中,这就是它所做的。现在它是一个可选的,包含一个包含 nil 的可选。这不是一个 nil 值的可选 - 这是一个包含值的可选(包含 nil 的可选)。解包给你一个包含 nil 的可选。 似乎什么都没发生。但它确实发生了 - 它被第二次包裹,然后解开一次。

如果您使用 swiftc -dump-ast source.swift 编译您的示例代码,您可以看到这一点。您会看到短语 inject_into_optional implicit type='Int??'Int?? 是一个包含可选值的可选值。

Optionals 包含 optionals 并不是模糊的边缘情况——它们很容易发生。例如,如果您曾经 for...in 遍历包含可选值的数组,或使用下标从包含可选值的字典中获取值,那么该过程涉及可选值的可选值。

另一种思考方式是,如果您将 if let x = y { } 想成*像一个函数,if_let,定义如下:

func if_let<T>(optVal: T?, block: T->()) {
if optVal != nil {
block(optVal!)
}
}

现在想象一下,如果您提供一个采用 Int?block – 也就是说,T 将是一个 Int?。所以 T? 将是一个 Int??。当您将常规 Int? 与该 block 一起传递到 if_let 时,Swift 会隐式地将其升级为 Int?? 以使其编译.这基本上就是 if let not_unwrapped_a:Int? 发生的事情。

我同意,隐式可选升级有时会令人惊讶(更令人惊讶的是 Swift 会升级返回可选值的函数,即如果一个函数采用 (Int)->Int?,它将升级 (Int)->Int 以返回一个可选的)。但大概感觉是,在这种情况下,为了方便起见,潜在的困惑是值得的。

* 只是一种

关于ios - if let 在显式指定类型时表现得很奇怪,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27569694/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com