Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/wordpress/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift 超载??具有结果类型的运算符_Swift - Fatal编程技术网

Swift 超载??具有结果类型的运算符

Swift 超载??具有结果类型的运算符,swift,Swift,我正在阅读并演示选项,第8章提到如何定义??运算符来处理结果类型,这是以前定义的类型。然而,当我尝试使用这个操作符时,我没有看到重载版本被调用。我是否错误地使用了此运算符 // Define ErrorType enum LookupError: ErrorType { case CapitalNotFound case PopulationNotFound } enum Result<T> { case Success(T) case Error(

我正在阅读并演示选项,第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)
    }
}

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

您的
r
是一个
结果
包装在一个
可选的
中,因此您得到了适用于可选的
??
运算符的版本

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

let r:Result<String> = Result<String>.Success("A-Ok")
let d = Result<String>.Success("Error")
let result = r ?? d
让r:Result=Result.Success(“A-Ok”)
设d=Result.Success(“Error”)
设结果=r??D

你是表达式
让结果=r??d
与重载的函数签名不匹配,因此它不知道您要调用的是您的函数(而是调用常规的nil合并运算符)

让我们看看签名:

func ??<T>(result: Result<T>, handleError: ErrorType -> T) -> T { ...
现在,为了在调用函数签名时与函数签名一致,我们将表达式的右侧构造为闭包,如下所示:

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 */
好的,现在我们实际上称你的
重载。然而,上面的这些表达式看起来相当混乱,特别是如果我们想频繁调用自定义的
操作符

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

func myStringErrHandler () -> (ErrorType -> String) {
    return { (err: ErrorType) -> (String) in
        switch err as! LookupError {
        case .CapitalNotFound: return "Couldn't find capital"
        case .PopulationNotFound: return "Couldn't find population"
    }
}
let errHandle = myStringErrHandler()

var result = r ?? errHandle
print(result) /* A-Ok */

result = d ?? errHandle
print(result) /* Couldn't find capital */

这可能会做得更整洁,但您明白了要点:我们必须确保调用及其参数符合自定义函数的签名

d
此处不符合预期的
ErrorType->String
闭包,即自定义
??
函数中的第二个参数(rhs)。因此,这将不会调用自定义的
函数。啊,很好。我只讨论了第一个参数类型的问题,但需要解决两个方面的问题。我被Swift对nil合并运算符的定义甩了,它的定义如下:public func??(可选:T?,@autoclosure defaultValue:()throws->T)rethrows->T defaultValue参数看起来像是接受了一个没有任何参数的函数,返回了一个类型为T的值。由于Swift lang版本没有接受函数,我假设上面的版本也不会接受。您是对的,对于本机
??
案例,第二个参数是闭包,即使它看起来可以像是
T
类型的单个参数一样使用。这里的关键是关键字
@autoclosure
,它允许不带任何参数的闭包函数参数作为参数发送到函数,而不必包装在
{…}
中。因此,在本机
rhs
lhs??rhs
实际上描述了闭包的return语句
()->T
(您可以将其视为
lhs???{return rhs}
)。原因是我们可以懒散地评估
rhs
(因为它是一个闭包)。。。。。。因为如果我们选择的话,
rhs
(闭包返回值)的实际值只会在函数
中“评估”:我们只希望在
lhs
包含
nil
的情况下如此。因此(抛开错误不谈),对于本机
,我们还可以将第二个参数定义为标准的单变量参数,但这样就不会对进行延迟计算,如果我们永远无法到达nil合并表达式的右侧,这将是浪费。有点过时,但对学习仍然有用,请参见:
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 */
func myStringErrHandler () -> (ErrorType -> String) {
    return { (err: ErrorType) -> (String) in
        switch err as! LookupError {
        case .CapitalNotFound: return "Couldn't find capital"
        case .PopulationNotFound: return "Couldn't find population"
    }
}
let errHandle = myStringErrHandler()

var result = r ?? errHandle
print(result) /* A-Ok */

result = d ?? errHandle
print(result) /* Couldn't find capital */