在 Swift 中调用递归函数中的重载函数
Calling an overloaded function in recursive function in 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([=11=]))}
return newArray!
}
func accumulate (_ acc: (Element) throws -> [Element]) rethrows -> [[Element]] {
var newArray : [[Element]]?
try self.forEach{try newArray?.append(acc([=11=]))}
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
请告诉我我的代码有什么问题并解释原因。
非常感谢!
您遇到的问题与超载本身无关。您在尝试强制展开的每个变体中只有 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([=10=]))}
// 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] = []
如果您仍在学习 swift,我建议采用“永远不要强制展开(除非完全必要)”规则。此外,我建议也不要强制转换。您几乎总是可以不费力地重写代码 unwrap/cast.
有几点需要注意:
- 这里最直接的问题是你要强制解包
newArray
,这是一个你用 nil 初始化的可选变量,但永远不会分配 non-nil 值。
- 您必须重载
accumulate
,但它们可以与泛型合并。
- 你的
accumulate
实际上是 map
。术语“累积”通常与 reduce
/fold
操作相关联。
- 您的
appendTo(_:)
功能不可靠。
- 根据Swift的命名规则,应该是
append(to:)
。但这没有意义,因为 arg 不是附加到的内容,而是附加的内容。我建议简单地命名它 append(_:)
.
- 它并没有比直接使用
+
运算符增加多少价值
- 你的
recurse
函数实际上并没有递归。
我会这样写:
import Foundation
//Solution goes in Sources
extension Array where Element: Comparable {
func myMap<T>(_ transform: (Element) throws -> T) rethrows -> [T] {
var newArray = [T]()
newArray.reserveCapacity(self.count)
for element in self {
try newArray.append(transform(element))
}
return newArray
}
}
let input = ["a", "b", "c"]
let expected = [
["a1", "a2", "a3"],
["b1", "b2", "b3"],
["c1", "c2", "c3"],
]
func nameMeBetter(_ input: String) -> [String] {
return ["1", "2", "3"].myMap { input + [=10=] }
}
let result = input.myMap(nameMeBetter)
print(result)
由于myMap(_:)
与内置的Sequence.map(_:)
一样,我们可以直接使用它。
所有这些代码简单地归结为:
let input = ["a", "b", "c"]
let expected = [
["a1", "a2", "a3"],
["b1", "b2", "b3"],
["c1", "c2", "c3"],
]
let result = input.map { char in
["1", "2", "3"].map { digit in
char + digit
}
}
print(result)
我正在做一个在线学习练习 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([=11=]))}
return newArray!
}
func accumulate (_ acc: (Element) throws -> [Element]) rethrows -> [[Element]] {
var newArray : [[Element]]?
try self.forEach{try newArray?.append(acc([=11=]))}
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
请告诉我我的代码有什么问题并解释原因。
非常感谢!
您遇到的问题与超载本身无关。您在尝试强制展开的每个变体中只有 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([=10=]))}
// 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] = []
如果您仍在学习 swift,我建议采用“永远不要强制展开(除非完全必要)”规则。此外,我建议也不要强制转换。您几乎总是可以不费力地重写代码 unwrap/cast.
有几点需要注意:
- 这里最直接的问题是你要强制解包
newArray
,这是一个你用 nil 初始化的可选变量,但永远不会分配 non-nil 值。 - 您必须重载
accumulate
,但它们可以与泛型合并。 - 你的
accumulate
实际上是map
。术语“累积”通常与reduce
/fold
操作相关联。 - 您的
appendTo(_:)
功能不可靠。- 根据Swift的命名规则,应该是
append(to:)
。但这没有意义,因为 arg 不是附加到的内容,而是附加的内容。我建议简单地命名它append(_:)
. - 它并没有比直接使用
+
运算符增加多少价值
- 根据Swift的命名规则,应该是
- 你的
recurse
函数实际上并没有递归。
我会这样写:
import Foundation
//Solution goes in Sources
extension Array where Element: Comparable {
func myMap<T>(_ transform: (Element) throws -> T) rethrows -> [T] {
var newArray = [T]()
newArray.reserveCapacity(self.count)
for element in self {
try newArray.append(transform(element))
}
return newArray
}
}
let input = ["a", "b", "c"]
let expected = [
["a1", "a2", "a3"],
["b1", "b2", "b3"],
["c1", "c2", "c3"],
]
func nameMeBetter(_ input: String) -> [String] {
return ["1", "2", "3"].myMap { input + [=10=] }
}
let result = input.myMap(nameMeBetter)
print(result)
由于myMap(_:)
与内置的Sequence.map(_:)
一样,我们可以直接使用它。
所有这些代码简单地归结为:
let input = ["a", "b", "c"]
let expected = [
["a1", "a2", "a3"],
["b1", "b2", "b3"],
["c1", "c2", "c3"],
]
let result = input.map { char in
["1", "2", "3"].map { digit in
char + digit
}
}
print(result)