gpt4 book ai didi

ios - 为什么守卫会破坏类型推断?

转载 作者:可可西里 更新时间:2023-10-31 23:59:46 26 4
gpt4 key购买 nike

我遇到过如标题所描述的问题:guard 语句由于某种原因破坏了类型推断。我创建了一个 Playground 项目来玩。

以下是一些用于设置的样板代码:

import Foundation

struct Model: Decodable {
var i: String
}

let jsonString = """
{
"i": "yes"
}
"""

let jsonData = jsonString.data(using: .utf8)
let theModel = try JSONDecoder().decode(Model.self, from: jsonData!)

struct Response<T> {
var decodedData: T?
}

enum Result<Value> {
case success(Value)
case failure
}

struct Client {
static let shared = Client()
private init() {}

func execute<T: Decodable>(completion: (Response<T>) -> ()) {
let decodedData = try! JSONDecoder().decode(T.self, from: jsonData!)
completion(Response(decodedData: decodedData))
}
}

问题是:

struct ServicesA {
func loadSomething(completion: (Result<Model>) -> ()) {
Client.shared.execute { result in // error: generic parameter 'T' could not be inferred
guard let decodedData = result.decodedData else { return }
completion(Result.success(decodedData))
}
}
}

struct ServicesB {
func loadSomething(completion: (Result<Model>) -> ()) {
Client.shared.execute { result in
completion(Result.success(result.decodedData!))
}
}
}

ServicesA 中断,而 ServicesB 编译。

如您所见,唯一的区别是guard let decodedData = result.decodedData else { return } 。它破坏了类型推断,因此 Client.shared.execute 函数会提示无法推断出 T

我想知道为什么会发生这种情况以及处理这个问题最合适的方法是什么。

最佳答案

TLDR;单行闭包编译不同于多行

长答案:让我们暂时忘记单行闭包。当我们编写接受泛型作为参数类型的泛型函数然后调用此函数时,编译器需要在调用时知道所需函数的类型是什么,即其参数的类型。现在考虑这个参数是一个闭包。同样,编译器需要知道调用时闭包的类型(函数签名)。这个信息应该在闭包的签名中可用(即参数和返回类型),编译器不担心(这是正确的)闭包的主体。因此,服务 A 的行为完全符合编译器的预期,即闭包签名没有提供任何有关其类型的线索。

现在采用单行关闭。 Swift 编译器仅针对单行闭包内置了类型推断优化。当您编写单行闭包时,编译器首先启动其类型推断,并尝试从其唯一的单行 body 中找出闭包,包括其返回类型等。这种类型推断适用于单行闭包(有或没有泛型上下文)。这种类型推断是您的服务 B 工作的原因

所以我将问题改写为“为什么类型推断适用于单行闭包?”因为这是 Swift 为单行闭包提供的额外特性。一旦你转向多行闭包(它不是特定于 guard 语句,如果你也放置 print(“hello world”) 也会发生同样的情况),这种类型推断就不再可用。尽管可能还有其他类型的推理检查可用于多行闭包。

您可以做的只是在闭包签名中提供类型信息即(结果:Response<模型>)

关于ios - 为什么守卫会破坏类型推断?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50625011/

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