gpt4 book ai didi

作为参数传递的 Swift `rethrows` 函数导致编译器错误

转载 作者:可可西里 更新时间:2023-11-01 00:23:18 29 4
gpt4 key购买 nike

在 Swift 2 中,以下函数不会编译,即使函数中的所有调用都不会抛出。

func function1<T, U>(f: Optional<T -> U>, x: Optional<T>) -> Optional<U> {
return f.flatMap(x.map) // Call can throw, but it is not marked with 'try' and the error is not handled
}

此版本的函数与第一个版本相同(并且更冗长),但它可以编译。

func function2<T, U>(f: Optional<T -> U>, x: Optional<T>) -> Optional<U> {
return f.flatMap { g in
x.map(g)
}
}

最佳答案

这些版本并不相同,我会解释原因。

假设您有一个rethrows 函数,因为它接受throwing 函数作为参数:

func a(x: () throws -> ()) rethrows {
try x()
}

所以 a(x) 仅在 x() 抛出时抛出。

如果你有函数 b 抛出:

func b() throws {
}

然后你必须用try调用a(b):

try a(b)
a(b) // gives "Call can throw but is not marked with 'try'"

但是如果你传递给 a 而不是抛出函数:

func c() {
}

然后 Swift 编译器足够聪明,可以确定 a 函数体中的 x() 实际上并没有抛出,它允许简单地调用 a(c) :

a(c) // it's ok

这是因为:

The throws keyword is part of a function’s type, and nonthrowing functions are subtypes of throwing functions. As a result, you can use a nonthrowing function in the same places as a throwing one.

回到你的例子。

Optional.flatMap() 定义为:

public func flatMap<U>(@noescape f: (Wrapped) throws -> U?) rethrows -> U?

在您的示例中,f.flatMap 的类型为 ((T -> U) throws -> U?) rethrows -> U?

你看到它重新抛出,因为它接受抛出函数参数并且必须使用 try 调用,除非 f 的类型为 Wrapped -> U? 并且不会抛出。

Optional.map 定义为:

public func map<U>(@noescape f: (Wrapped) throws -> U) rethrows -> U?

因此 x.map 具有类型 (T throws -> U) rethrows -> U?

当您调用 f.flatMap { g in x.map(g) } 时,编译器会看到 g 具有 T -> U 类型并且不会抛出 x.map(g){ g in x.map(g) } f.flatMap { g in x.map( g) 都是安全的,不抛出。

但是当你调用 f.flatMap(x.map) 时,编译器看到的只是 x.map(T throws -> U) rethrows -> U? 键入并可以(重新)抛出,所以 f.flatMap(x.map) 不安全,也可以(重新)抛出并且必须使用 调用尝试

关于作为参数传递的 Swift `rethrows` 函数导致编译器错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34080691/

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