【发布时间】:2017-10-25 19:34:12
【问题描述】:
我正在尝试通过泛型实现平面地图。 (是的,flatmap 已经是该语言的一部分。)我的尝试使用通用的重载函数来实现这一点。 (可能不是最有效的。我知道。我已经有了一个有效的命令式版本。)我发现出乎意料的是 flatten< T, U >( _ elem: T ) -> [ U ] 正在消耗调用 flatten 的数组,即使存在重载 func flatten< T, U >( _ ary: [ T ] ) -> [ U ] 也是如此。
我可以知道出了什么问题,但我似乎看不出原因,甚至看不出去哪里了解原因并可能修复它。
我什至尝试了一些演员表,只是为了看看,结果产生了错误,这对我来说很有意义。为什么要将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]
【问题讨论】:
-
比较stackoverflow.com/q/41980001/2976878——对
flatten的递归调用的重载解决发生在flatten本身的实现中。从那个位置,编译器所知道的关于ary.first的所有信息就是它是某种类型的T?;因此它不能分派到采用[T]的flatten的重载。 -
如果您的问题被标记为重复,只需进行编辑并解释为什么它不是重复的(希望问题会重新打开)。此外,如果您的问题纯粹是转发,请不要转发。如果它们是相关的,则将它们链接起来,并在需要时解释它们是如何相关的。如果不是,那么最好不要在您的问题中讨论它们。
-
@Hamish,感谢您的回复和链接。那里有很多好东西。比我想象的还要棘手。
-
@Honey,谢谢。我会的,但问题实际上是重复的。无意的。这就是我提出这个问题的原因。我确实重新/搜索了我的答案,但是对于 Swift,它仍然非常……对我来说很不寻常。例如,对于模棱两可的下标,我会得到一个编译器错误,并且无法找出原因,因为真正的错误实际上是类型不匹配。然而,如果编译器说“无法转换 ArraySlice ...”,我什至不必发布我的(其他)问题。我刚刚修复了我的 n00b 错误。 :)。
标签: swift generics higher-order-functions