如何在Swift 3.0中紧凑地编写Array
的扩展名,该扩展名适用于Float
和Double
Element
类型?
以下不起作用:
extension Array where Element: FloatingPoint
{
public func multiply(mult: Double) -> [Double] {
return self.map{Double($0) * mult}
}
}
错误是
无法在当前上下文中推断闭包类型
为什么不能推断出闭包类型?这是编译器的当前限制,还是有充分理由不能推断出闭包类型?
更明确的版本也不起作用:
extension Array where Element: FloatingPoint
{
public func multiply(mult: Double) -> [Double] {
return self.map{(x: Element) -> Double in Double(v: x) * mult}
}
}
这次出现错误
对成员'*'的歧义提及
我再也不确定这个错误的原因。
答案 0 :(得分:2)
逻辑上,您的扩展应该通过将同类浮点类型数组与相同类型的值相乘并返回该类型的数组来工作。您可以使用Element
类型的参数以及[Element]
的返回来表达此信息:
// this could also just be an extension of Sequence
extension Array where Element : FloatingPoint {
public func multiply(by factor: Element) -> [Element] {
return self.map { $0 * factor }
}
}
因此对于[Float]
,这会接受Float
类型的参数并返回[Float]
。
但是,如果我确实想要返回
,该怎么办?Double
数组?
我不相信可以从任意Double
(或甚至FloatingPoint
)符合的实例构建BinaryFloatingPoint
协议(尽管它们确实需要实现IEEE 754规范的各个方面)实际上定义了符合类型的精确编码。
但是,如果真的想要这个,你可以写两个重载 - 一个用于Float
元素,一个用于Double
元素:
extension Sequence where Iterator.Element == Float {
public func multiply(by factor: Double) -> [Double] {
return self.map { Double($0) * factor }
}
}
extension Sequence where Iterator.Element == Double {
public func multiply(by factor: Double) -> [Double] {
return self.map { $0 * factor }
}
}
或者,如果您计划使用更广泛的类型进行此工作,则可以使用protocol
来定义允许符合类型将其值表示为Double
的要求:
protocol ConvertibleToDouble {
func _asDouble() -> Double
}
extension Float : ConvertibleToDouble {
func _asDouble() -> Double { return Double(self) }
}
extension Double : ConvertibleToDouble {
func _asDouble() -> Double { return self }
}
extension Sequence where Iterator.Element : ConvertibleToDouble {
func multiply(by factor: Double) -> [Double] {
return self.map { $0._asDouble() * factor }
}
}