我想扩展Array
类,但仅适用于符合SequenceType
协议的元素。
我想写的代码/我认为合理的代码是:
extension Array {
func flatten<T: SequenceType>() -> [T.Generator.Element] {
var result = [T.Generator.Element]() // *** [2]
for seq: T in self { // *** [1]
for elem in seq {
result += [elem]
}
}
return result
}
}
然而,Swift似乎创建了T
的两个版本。我假设一个来自正常的Array
声明,另一个来自对我的方法的尝试约束。
特别是,这意味着第[1]行给出了可爱的错误'T' is not convertible to 'T'
。
类似地,[2]处的行失败,因为在该上下文中,Swift不会将T
识别为具有.Generator
成员(尽管声明中的返回类型注释有效)。
我已经尝试了许多其他配方(包括使用,例如T where T: SequenceType
),但我似乎找不到表达这种约束的方法。
这是可能的,还是我在错误的树上咆哮?
答案 0 :(得分:2)
作为你的问题的评论者已经说过,答案是否定的。但是,从Swift标准库的组织中可以清楚地看出,不鼓励将专用泛型函数编写为方法。 (我怀疑随着Swift的类型系统的发展,它会发生变化。)例如,请注意Swift的本机数组类型没有contains
方法。 相反,它被实现为全局函数,因为要求元素为Equatable
。这正是因为您遇到的限制:无法在方法中专门化封闭类的泛型类型参数,无论它是否为扩展名。 (在我看来,这是一个非常不幸的限制。)
所以,正如斯威夫特目前的立场,我会&#34;实施&#34; flatten
只需使用join
,例如join([], arrayOfArrays)
。
答案 1 :(得分:2)
现在可以使用Swift 2:
extension SequenceType where Generator.Element : SequenceType {
func flatten() -> [Generator.Element.Generator.Element] {
var result: [Generator.Element.Generator.Element] = []
for seq in self {
result += seq
}
return result
}
}
[[1,2,3],[],[2,4,5]].flatten() // [1, 2, 3, 2, 4, 5]
请注意,虽然我们在库中有flatMap,但这个特定功能并不重要。