Arrays 具有多个闭包的泛型函数不起作用
我想创建一个泛型函数,它可以将数组聚合为一种类型。我将用一个愚蠢但简单的例子来解释 假设我得到了这个代码:Arrays 具有多个闭包的泛型函数不起作用,arrays,swift,generics,closures,Arrays,Swift,Generics,Closures,我想创建一个泛型函数,它可以将数组聚合为一种类型。我将用一个愚蠢但简单的例子来解释 假设我得到了这个代码: class Entity { var someElement: Int } 现在,我已经在数组扩展中编写了此函数,以便可以在任何数组上使用它: /** * An aggregation function. The first closure extracts the useful data in a new object, the second one aggregates t
class Entity {
var someElement: Int
}
现在,我已经在数组扩展中编写了此函数,以便可以在任何数组上使用它:
/**
* An aggregation function. The first closure extracts the useful data in a new object, the second one aggregates two items of the same type in one.
*
* The algorithm works from front to back
*
* @return the aggregated value or nil if the array is empty
*/
func aggregate<R>(translation: (T) -> R, aggregation: (R, R) -> R) -> R? {
if count == 0 {
return nil
}
if count == 1 {
return translation(self.first!)
}
var calc = translation(self.first!)
for item in 1..<count {
calc = aggregation(calc, translation(self[item]))
}
return calc
}
但我得到了这个疯狂的错误。我得到了这个疯狂的错误。我得到了这个疯狂的错误:<代码>不能转换表达的类型((((((((((($T5)T5)->((((((((($T5)5)->(((((($T5)5)->((((((((($T5)5))->((((((((((((((((($T5)5))->)T5)->(((((((($T5)T5)T4)))->((((((((((($T5)T4)T4)T4)T4)T4)T4))))))->((((((((((((((($T4)T4)T4)T4)T4)T4)T4)T4)T4)))))))))))->$T6,$T8)->$T6)->$T6)->
到底发生了什么事?在Xcode中,当我检查项的类型时,它是
,因此它甚至不能编译到那里。是否需要指定函数调用中的R?看起来斯威夫特在推断第一个闭包的类型时遇到了问题。如果更新对聚合的调用以显式提供类型:
array.aggregate(
{
(item: Entity)->Int in
return item.someElement
}, aggregation: {
(item1, item2) in
return item1 + item2
}
)
它编译/运行正常
有趣的是,如果不使用显式返回,则推理可以正常工作:
array.aggregate(
{
item in
item.someElement
}, aggregation: {
(item1, item2) in
return item1 + item2
})
(array.aggregate({$0.someElement},+)
也可以正常工作)
另外,如果您对替代方案感兴趣,您可以重写aggregate
,如下所示:
extension Array {
func aggregate<R>(translation: T -> R, aggregation: (R, R) -> R) -> R? {
return self.first.map { fst in
dropFirst(self).reduce(translation(fst)) { aggregation($0, translation($1)) }
}
}
}
扩展数组{
函数聚合(翻译:T->R,聚合:(R,R)->R)->R{
返回self.first.map{fst in
dropFirst(self).reduce(translation(fst)){aggregation($0,translation($1))}
}
}
}
是的,我想这可能就是问题所在。谢谢你的解决方案!编辑:我想这只是测试版,我希望在下一个版本中可以修复。我将对此提交一份错误报告。此外,使用map函数也是一个好主意,我将测试两种不同的方法的速度,并使用最快的方法。我已经在一个for
循环中运行了一个多达10K个元素的测试,每次添加一个元素。结果以csv格式打印并可用(数据以纳秒为单位)。我创造了。伙计,在我2011年初的基础MBP上,创建这个图表花了很多时间。我想是时候升级了。TL;DR:您的mapreduce方式的速度大约是2或3倍。
extension Array {
func aggregate<R>(translation: T -> R, aggregation: (R, R) -> R) -> R? {
return self.first.map { fst in
dropFirst(self).reduce(translation(fst)) { aggregation($0, translation($1)) }
}
}
}