我有以下两个函数(编译时不会出错):

func hasLocalChanges() -> Bool {
    return false
}

func hasRemoteChanges() async -> Bool {
    return await Task{ true }.value
}

现在,假设我想引入第三个函数,如下所示:

func hasChanges() async -> Bool {
    return self.hasLocalChanges() || await self.hasRemoteChanges()
}

然后,此函数将给我一个编译器错误,说明:

'async' call in an autoclosure that does not support concurrency

但为什么呢?

我可以通过交换操作数来解决此错误…

func hasChanges() async -> Bool {
    return await self.hasRemoteChanges() || self.hasLocalChanges()
}

,这将再次使代码编译无误.

但我真的想利用延迟求值,最后执行异步函数.因此,实现这一目标的唯一方法是说…

func hasChanges() async -> Bool {
    if !self.hasLocalChanges() {
        return await self.hasRemoteChanges()
    } else {
        return true
    }
}

…这似乎有点麻烦.

有谁能解释一下为什么我一开始就犯了这个错误?


EDIT:

非常感谢@aciniglio:

重写代码的一种方法如下(假设这两个函数也允许抛出):

func hasChanges() async throws -> Bool {
    return try await hasLocalChanges().or(await hasRemoteChanges())
}

extension Bool {
    func or(_ other: @autoclosure () async throws -> Bool) async rethrows -> Bool {
        return self ? true : try await other()
    }
}

推荐答案

这是因为||实际上是一个希望右侧看起来像rhs: @autoclosure () throws -> Bool的函数(与例如rhs: @autoclosure () async throws -> Bool相比)

参见此处的来源:https://github.com/apple/swift/blob/e6cbf5483237aa593bdbafb6c7db7ebcb2d0e26a/stdlib/public/core/Bool.swift#L320

首先移动await时,它将解析为布尔值,然后self.hasLocalChanges()是非异步() throws -> Bool

下面编译的示例

    func hasChanges() async -> Bool {
        return or( a: await hasRemoteChanges(), b: hasLocalChanges())
    }
    
    // This is pretty much what `||` looks like today
    func or(a: Bool, b: @autoclosure () throws -> Bool) -> Bool {
        return a ? true : try b()
    }
    func hasChanges() async -> Bool {
        return await or( a: hasLocalChanges(), b: await hasRemoteChanges())
    }
    
    // This is what an `async` friendly `||` could look like. 
    // Note that the caller would need to await the result.
    func or(a: Bool, b: @autoclosure () async throws -> Bool) async -> Bool {
        return a ? true : try! await b()
    }

Ios相关问答推荐

如何在iPhone 15上消除.NET Maui中状态栏和页面之间的差距

在工作表上移动图像SwiftUI

如何将模糊输入/模糊输出添加到SwiftUI中的非对称过渡?

IOS:在UI线程中执行代码的闭包样式的替代

如何使用 Rxswift 处理程序最喜欢的按钮

react 本机 |错误:无法解析 node_modules/react-native/index.js 中的模块

带有属性包装器的不可用属性

Swift如何表示单位转换的标准大气压

使用swift将图像转换为A4大小的pdf

如何将标准化坐标系中的点的位置转换为具有相对位置的常规坐标系?

UIButton在iOS7中没有显示突出显示

在 Swift 中禁用向后滑动手势

在滚动视图中使用动态大小的控制器调整容器视图的大小

如何用 CAShapeLayer 和 UIBezierPath 画一个光滑的圆?

比较没有时间分量的 NSDates

Swift - 获取设备的 WIFI IP 地址

从故事板导航到其他 Swift 1.2 文件时 Xcode 6.3 崩溃

为给定的 UIColor 获取更亮和更暗的 colored颜色 变化

如何为 UILabel 的背景 colored颜色 设置动画?

iOS13状态栏背景 colored颜色 与大文本模式下的导航栏不同