我正在尝试通过泛型实现平面 map 。 (是的,平面 map 已经是该语言的一部分。)我尝试使用通用的重载函数来完成此任务。 (可能不是最有效的。我知道。我已经有了一个有效的命令式版本。)令我意想不到的是 flatten< T, U >( _ elem: T ) -> [ U ]
即使重载 func flatten< T, U >( _ ary: [ T ] ) -> [ U ]
也正在消耗调用 flatten 的数组存在。
我知道出了什么问题,但我似乎不明白为什么,甚至不知道去哪里了解原因并可能修复它。
我什至尝试了几次转换,只是为了看看,这产生了错误,这对我来说是有意义的。为什么投 T
至T
或[ T ]
至[ T ]
?。又改了ary
至elem
看看这是否导致重载语义出现问题。产生相同的输出。
import Foundation
func flatten< T, U >( _ elem: T ) -> [ U ] {
if let item = elem as? U {
return [ item ]
} else {
return []
}
}
func flatten< T, U >( _ ary: [ T ] ) -> [ U ] {
if ary.count == 0 {
return []
}
return flatten( ary.first ) + flatten( Array( ary.dropFirst() ) )
}
let x: [ Int ] = flatten( [ 1, 2, [ 3, 4 ], [ [ 5, 6 ], nil, 7 ], 8, 9 ] )
print( x ) // Prints [1, 2, 8, 9 ] instead of [1, 2, 3, 4, 5, 6, 7, 8, 9]
最佳答案
编译器因使用来自 ary.first 的包装可选而感到困惑,它肯定会转到第一个函数签名。但即使解决了这个问题,在处理更简单的情况(例如 [[1,2][3,4]] 时仍然会留下一些歧义。
解决此问题的另一种方法是在内部处理所有类型,而不是将其留给编译器:
func flatten<U>( _ ary:[Any] ) -> [ U ]
{
func makeFlat(_ flat:[U], _ elem:Any) -> [U]
{
if let item = elem as? U { return flat + [item] }
if let ary = elem as? [U] { return flat + ary }
if let subAry = elem as? [Any] { return flat + flatten(subAry) }
return flat
}
return ary.reduce([U](),makeFlat)
}
关于swift - 具有通用参数或 T 或 T 数组的 Swift 重载函数中的意外行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46940722/