【问题标题】:How to declare a rethrowing function?如何声明重新抛出函数?
【发布时间】:2018-09-15 07:18:48
【问题描述】:

我实现了以下函数 - 作为布尔数组的扩展 - 这可能会引发 CustomError 错误:

enum CustomError: Error {
    case empty
    case doesNotContainTrue
}

extension Array where Element == Bool {
    func indexOfFirstTrue() throws -> Int {
        if isEmpty { throw CustomError.empty }

        guard let detectedIndex = index(of: true) else {
            throw CustomError.doesNotContainTrue
        }

        return detectedIndex
    }
}

按预期工作:

let myArray = [false, true, false, true]
try print(myArray.indexOfFirstTrue()) // 1

接下来,我尝试将函数声明为:

func handleResult(_ index: Int) throws {
    print(index * 2)
    // ...
}

它应该获取myArray.indexOfFirstTrue() 的结果并对其进行处理(为简单起见,我们假设它打印乘以 2 的值):

try handleResult(myArray.indexOfFirstTrue()) // 2

我想做的是将handleResult声明为重新抛出函数

可以使用 rethrows 关键字声明函数或方法 表明它仅在其功能之一时引发错误 参数抛出错误。这些功能和方法被称为 重新抛出函数和重新抛出方法。重新抛出函数和 方法必须至少有一个抛出函数参数。

The Swift Programming Language (Swift 4.1): Declarations - Rethrowing Functions and Methods.

所以我可以用非抛出公式调用它,因此它不会抛出错误:

handleResult(myArray.indexOfFirstTrue()) // 2

但我不知道应该编辑什么才能让它成为一个重新抛出的函数,所以我试图将它声明为:

func handleResult(_ index: Int) rethrows {
    print(index * 2)
}

我得到了以下错误:

错误:'rethrows' 函数必须接受一个 throwing 函数参数

因此,我也尝试将其声明为:

func handleResult(_ index: (() throws ->  Int)) rethrows {
    print(index * 2)
}

显然得到了以下错误:

错误:无法将“Int”类型的值转换为预期的参数类型 '() 抛出 -> Int'

此时我该怎么办?

【问题讨论】:

  • 为什么handleResult要重新抛出?据我所知,您只希望indexOfFirstTrue 抛出。您仍然可以将其称为try handleResult(myArray.indexOfFirstTrue())
  • 无关,但您获取detectedIndex 的逻辑可以简化为guard let detectedIndex = index(of: true) else { throw CustomError.doesNotContainTrue }
  • 感谢@Hamish 的留言 :)

标签: swift rethrow


【解决方案1】:

记住,参数的类型是() -> Int!所以你需要调用传入的函数来得到结果!您还需要try,因为该函数可以抛出。

func handleResult(_ index: (() throws ->  Int)) rethrows {
    print(try index() * 2) // see the "()"?
}

现在你可以像这样使用它了:

let myArray = [true]
try handleResult(myArray.indexOfFirstTrue)

【讨论】:

  • 谢谢伙计。根据您的回答,我仍然必须使用 try (try handleResult(myArray.indexOfFirstTrue)) 来调用它,这是我试图避免的。那么我应该怎么做才能打电话给handleResult(myArray.indexOfFirstTrue)
  • @AhmadF 然后你必须处理handleResult内部的错误,并删除rethrows
  • 你提到的对我来说似乎是合乎逻辑的,但是,我想知道-那么map函数的逻辑是如何工作的?!如this answer 中所述,map 可以采用非抛出函数,这在我的情况下是不允许的,如果我们尝试:func getValue() -> Int { return 2 } handleResult(getValue()) 它将不起作用。感谢您的耐心?
  • @AhmadF 你应该通过不带括号的getValuehandleResult(getValue) 记住你没有调用函数!另外,你可以这样写handleResult { 2 }
  • 天哪!哦,伙计,我也犯了同样的错误……这就是我的意思:我想在没有 try (handleResult { 1 }) 的情况下调用它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-19
  • 1970-01-01
  • 2013-05-02
  • 1970-01-01
相关资源
最近更新 更多