超载??结果类型的运算符

时间:2016-01-03 02:39:31

标签: swift

我正在阅读Functional Swift book并演示Optionals,第8章提到了如何定义??运算符来处理结果类型,这是以前定义的类型。但是,当我尝试使用此运算符时,我看不到调用的重载版本。我是否正确使用此操作符?

// Define ErrorType
enum LookupError: ErrorType {
    case CapitalNotFound
    case PopulationNotFound
}

enum Result<T> {
    case Success(T)
    case Error(ErrorType)
}

// Overloaded operator
func ??<T>(result: Result<T>, handleError: ErrorType -> T) -> T {
    print("overloaded result: \(result)")
    switch result {
    case let .Success(value): return value
    case let .Error(error): return handleError(error)
    }
}

我正在使用这样的运营商:

let r:Result<String>? = Result<String>.Success("A-Ok")
let d = Result<String>.Success("Error")
let result = r ?? d

这样做表明:

Result: Success("A-Ok")

但是在任何时候都不会调用重载的运算符。

2 个答案:

答案 0 :(得分:2)

你的表达式let result = r ?? d与你的重载的函数签名不匹配,因此它不知道你想要调用它的函数(而是调用常规的nil合并运算符)。 / p>

让我们来看看签名:

func ??<T>(result: Result<T>, handleError: ErrorType -> T) -> T { ...

您几乎可以正确使用调用中的第一个参数,它应该是Result<T>类型,但不是可选的。但是,自定义??函数中的第二个参数是闭包,一个函数类型ErrorType并返回泛型T(在我们的示例中:{{ 1}}),你的调用中的第二个参数必须是这样的闭包类型。因此,您的两个String实例Result<String>r不应与您的自定义d运算符一起使用,而应与相应的闭包一起使用。

定义??的两个示例实例 - 一个包含错误,一个包含成功---

Result<String>

现在,为了在我们对它的调用中符合你的var r:Result<String> = Result<String>.Success("A-Ok") var d:Result<String> = Result<String>.Error(LookupError.CapitalNotFound) 函数签名,我们将表达式的右侧构造成一个闭包,如下所示:

??

好的,现在我们实际上称你的var result = r ?? { err in switch err as! LookupError { case .CapitalNotFound: return "Couldn't find capital" case .PopulationNotFound: return "Couldn't find population" } } print(result) /* A-Ok */ result = d ?? { err in switch err as! LookupError { case .CapitalNotFound: return "Couldn't find capital" case .PopulationNotFound: return "Couldn't find population" } } print(result) /* Couldn't find capital */ 超载了。但是,上面的这些表达式看起来非常混乱,特别是如果我们想要经常调用我们的自定义??运算符。

不是每次执行错误检查时都发布相同的闭包,我们可以创建一个我们使用的闭包的句柄。使用句柄---就像上面的闭包一样---作为调用自定义??运算符的右侧参数:

??

这可能甚至可以做得更整洁,但你得到它的要点:我们必须确保我们的调用及其参数符合我们的自定义函数的签名。

答案 1 :(得分:0)

r Result包含在Optional中,因此您可以获得适用于期权的??运营商的版本。

由于您未在示例中使用可选性,因此您只需修复声明:

let r:Result<String> = Result<String>.Success("A-Ok")
let d = Result<String>.Success("Error")
let result = r ?? d