首页 > 解决方案 > 在 Swift 的递归函数中调用重载函数

问题描述

我正在做一个学习 Swift 的在线练习。以下代码是一个测试用例,用于显示调用在递归情况下调用的函数的重载版本时的问题。

import Foundation

//Solution goes in Sources
extension Array where Element: Comparable {
    func accumulate (_ acc: (Element) throws -> Element) rethrows -> [Element] {
        var newArray : [Element]?
        
        try self.forEach{try newArray?.append(acc($0))}
        
        return newArray!
    }
    func accumulate (_ acc: (Element) throws -> [Element]) rethrows -> [[Element]] {
        var newArray : [[Element]]?
        
        try self.forEach{try newArray?.append(acc($0))}
        
        return newArray!
    }
}
let input =   ["a", "b", "c"]
let expected = [
    ["a1", "a2", "a3"],
    ["b1", "b2", "b3"],
    ["c1", "c2", "c3"]
] // The expected result of the statement on the bottom of this code
func recurse(_ input: String) -> [String] {
    func appendTo(_ innerInput: String) -> String {
        return input+innerInput
    }
    let result = ["1", "2", "3"].accumulate(appendTo)
    print("3")
    return result
}
let result = input.accumulate(recurse)

运行时,编译器没有报错,但运行时显示如下错误信息:

Fatal error: Unexpectedly found nil while unwrapping an Optional value
Current stack trace:
0    libswiftCore.so                    0x00007fa0d799c920 _swift_stdlib_reportFatalError + 69
1    libswiftCore.so                    0x00007fa0d78aaa06 <unavailable> + 3279366
2    libswiftCore.so                    0x00007fa0d78aad85 <unavailable> + 3280261
3    libswiftCore.so                    0x00007fa0d76d2810 _fatalErrorMessage(_:_:file:line:flags:) + 19
4    main                               0x000055df0a54ef3a <unavailable> + 7994
5    main                               0x000055df0a54e63e <unavailable> + 5694
6    libc.so.6                          0x00007fa0d6052ab0 __libc_start_main + 231
7    main                               0x000055df0a54e09a <unavailable> + 4250
exited, illegal instruction

请告诉我我的代码有什么问题并解释原因。

非常感谢!

标签: swiftoverloadingextension-methods

解决方案


您遇到的问题与重载本身无关。您只是 newArray = nil在尝试强制展开的每个变体中都有,例如:

func accumulate (_ acc: (Element) throws -> Element) rethrows -> [Element] {
    var newArray : [Element]? // here, newArray = nil
    
    // newArray is still nil, and newArray?.append does nothing
    try self.forEach{try newArray?.append(acc($0))}
    
    // new array is still nil, and you force unwrap nil, hence Unexpectedly found nil while unwrapping an Optional value
    return newArray!
}

要解决这个问题,您可以newArray在开始时分配一些值:

var newArray : [Element] = []

如果您仍在快速学习,我建议您采用“从不强制展开(除非完全必要)”规则。此外,我建议也不要强制施放。您几乎总是可以重写您的代码,而无需强制解包/强制转换。


推荐阅读