[英]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.