简体   繁体   English

如何在不支持并发的自动关闭中修复“'async'调用”?

[英]How to fix "'async' call in an autoclosure that does not support concurrency"?

I have these two functions (which compile without errors):我有这两个函数(编译时没有错误):

func hasLocalChanges() -> Bool {
    return false
}

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

Now, let's say I want to introduce a third function which will look like this:现在,假设我想引入第三个函数,如下所示:

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

Then this function will give me a compiler error saying:然后这个函数会给我一个编译器错误说:

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

But why is that?但这是为什么呢?

I can resolve the error by swapping the operands …我可以通过交换操作数来解决错误……

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

…, which, again, will make the code compile without errors. …,这又一次可以使代码编译时没有错误。

But I really want to make use of lazy evaluation and have the asynchronous function be executed last.但我真的很想利用惰性求值并让异步函数最后执行。 So the only way to achieve that would be to say …因此,实现这一目标的唯一方法就是说……

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

…, which seems a little cumbersome. ......,这似乎有点麻烦。

Can anyone explain to me why I am getting that error in the first place?谁能向我解释为什么我首先会遇到这个错误?


EDIT:编辑:

Thanks a lot to @aciniglio :非常感谢@aciniglio

One way to rewrite the code is like this (assuming the two functions are also allowed to throw):重写代码的一种方法是这样的(假设两个函数也被允许抛出):

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()
    }
}

It's because ||这是因为|| is actually a function that wants the right hand side to look like rhs: @autoclosure () throws -> Bool (vs. eg rhs: @autoclosure () async throws -> Bool )实际上是一个希望右侧看起来像rhs: @autoclosure () throws -> Bool的函数(与例如rhs: @autoclosure () async throws -> Bool相比)

See the source here: https://github.com/apple/swift/blob/e6cbf5483237aa593bdbafb6c7db7ebcb2d0e26a/stdlib/public/core/Bool.swift#L320在此处查看源代码: https ://github.com/apple/swift/blob/e6cbf5483237aa593bdbafb6c7db7ebcb2d0e26a/stdlib/public/core/Bool.swift#L320

When you move the await first, it resolves into a boolean and then self.hasLocalChanges() is a non async () throws -> Bool当您首先移动 await 时,它会解析为布尔值,然后self.hasLocalChanges()是非 async () throws -> Bool

Examples that compile below下面编译的示例

    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()
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM