I was doing an online exercise for learing Swift. The following code is a test case singled out to show the issue with calling an overloaded version of a function that is called in a recursive situation.
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)
When run, the compiler didn't complain, but the runtime showed the following error message:
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
Please kindly tell me what wrong there is with my code and explain the reason.
Thank you very much!
The issue you're experiencing has nothing to do with overloading per se. You just have newArray = nil
in every variant that you try to force unwrap, for example:
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!
}
To fix that you can just assign some value to newArray
in the beginning:
var newArray : [Element] = []
If you're still learning swift, I would suggest to adopt the "never force unwrap (unless completely necessary)" rule. Additionally, I would suggest to never force cast as well. You can almost always rewrite your code without force unwrap/cast.