【问题标题】:Extension of Array of FloatingPoint Elements in Swift 3.0Swift 3.0 中浮点元素数组的扩展
【发布时间】:2017-01-25 16:26:50
【问题描述】:

如何在 Swift 3.0 中紧凑地编写 Array 的扩展,它适用于 FloatDouble 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}
    }
}

这次是错误

对成员“*”的模糊引用

我又不确定这个错误的原因。

【问题讨论】:

  • @Hamish 做你建议的工作,谢谢!这可能已经足够好了。但是,如果我确实想返回一个 Double 数组怎么办? (例如,考虑这样一种情况,而不是控制mult 参数的类型,如上例所示,我没有参数,而是乘以我没有编写的返回Double 的函数。在在这种情况下,将Array 元素乘以需要将它们转换为Double 并返回[Double] 的函数。
  • 我继续将我的 cmets 转换为答案 :)
  • @Hamish 您可能对使用初始化器的 DoubleConvertible 实现感兴趣,正如 Martin R 在此处 stackoverflow.com/questions/26794282/… 建议的那样,我在此处使用 stackoverflow.com/a/29179878/2303865
  • @LeoDabus 是的,这是解决“可以传递给给定函数重载的类型”问题的一个非常常见的解决方案(在本例中为Doubleinit(_:))。您实际上也可以对其进行概括,以便处理不同类型之间的转换,例如参见my answer here
  • @LeoDabus Swift 2 也有协议组合 ;) 它只是有不同的语法 (protocol<X, Y, Z>)。

标签: swift floating-point swift3 swift-extensions


【解决方案1】:

从逻辑上讲,您的扩展应该通过将同质浮点类型数组与相同类型的值相乘并返回该类型的数组来工作。您可以简单地用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 数组呢?

我不相信可以从任意符合FloatingPoint(甚至BinaryFloatingPoint)的实例构造Double,因为这两种协议都没有(尽管它们确实需要实现各个方面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 }
    }
}

【讨论】:

  • 我建议让它作为答案:)
  • Swift 不是已经有ConvertibleToDouble 协议或类似协议了吗?
  • @Danra 我不知道(请随意证明我错了:))
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多