gpt4 book ai didi

swift - 串行链接 do-try-catch 控制流的正确模式是什么?

转载 作者:可可西里 更新时间:2023-11-01 02:03:28 27 4
gpt4 key购买 nike

我正在寻找一种模式来处理在伪代码中看起来像这样的代码:

do:
try planA()
catch LikelyError e:
try planB()
catch Error e:
print ("we're hosed, there is no planC()")

在 swift 中,将 try- 放在 catch {} block 中并不能如上所示工作,相反,它似乎需要嵌套到它自己的 do {} block 中。这是它的样子:

enum ForeseenError : Error {
case likelyProblem
case unlikelyProblem
}

func planA () throws {
print ("planA")
throw ForeseenErrors.likelyProblem
}

func planB () throws {
print ("planB")
throw ForeseenErrors.unlikelyProblem
}

print ("Hello")
do {
try planA()
}
catch let error as ForeseenError {
print ("catch problem, trying planB")
do {
try planB()
}
catch let error {
print ("Unrecoverable error from planB")

/* if i had a planC() that potentially throws, then i'd
have to put it here in yet another nested do-try-catch
control flow structure */

}
}
catch let error {
print ("Unrecoverable error from planA")
}

print ("EOM")

这对我来说感觉像是一种反模式,因为它需要任意深度的嵌套来处理更多的选择。此外,虽然我可能希望针对尝试序列中不同深度的不可恢复错误使用不同的处理程序,但通常在最后一个 catch block 中捕获所有错误会更有意义。

那么社区,可以针对上述逻辑做些什么呢?

最佳答案

您可以使用自定义 .catch 操作定义您自己的可链接类型来解决此问题,并使用您自己的类 try 函数创建一个名为 attempt 的实例,如下所示以下内容:

class ChainableResult {
let error: Error? // could also use Result<T, Error> in a generics setting

init(error: Error?) {
self.error = error
}
}

func attempt(_ body: () throws -> ()) -> ChainableResult {
do {
try body()
return ChainableResult(error: nil)
} catch {
return ChainableResult(error: error)
}
}

extension ChainableResult {

@discardableResult // <- dangerous
func `catch`(_ body: (Error) throws -> ()) -> ChainableResult {
if let originalError = self.error {
do {
try body(originalError)
return ChainableResult(error: originalError)
} catch {
let newError = error
return ChainableResult(error: newError)
}
} else {
return ChainableResult(error: nil)
}
}
}

然后您可以像下面这样使用这些结构:

attempt {
try planA()
}.catch {
err in
try planB()
}.catch {
err in
print("I give up")
}

我将 @discardableResult 评论标记为危险,因为它允许您编写最终 catch 操作可以抛出的链,在这种情况下,抛出的错误将无法处理和忽略。

最终,我写了自己的 library for this .它可以防止像我提到的那样的危险情况,并且也可以与异步函数体一起使用。我上面给出的示例用法片段可以逐字复制和编译。

关于swift - 串行链接 do-try-catch 控制流的正确模式是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44742703/

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