Swift:乘以两个数字

问题描述 投票:0回答:2
protocol DArray: Sequence where Element: Numeric {
    var elements: [Element] { get set }
    subscript(index: Int) -> Element { get set }
    static func *(lhs: Self, rhs: Self) -> Self
}

struct Vector<Element: Numeric>: DArray {
    var elements: [Element]

    init(_ elements: [Element] = []) {
        self.elements = elements
    }

    ...

    static func *<T: DArray>(lhs: Self, rhs: T) -> Self {
        var v = lhs
        var result: Self
        for (i, element) in rhs.enumerated() {
            let e = v[i]
            let r = element * e
            // Cannot convert value of type 'Element' (generic parameter of generic struct 'Vector') to expected argument type 'T.Element' (associated type of protocol 'Sequence')
        }
        return result
    }
}

对于Numeric协议,文档说:

数字协议为在标量值,例如整数和浮点数。您可以编写可对标准中的任何数字类型进行操作的通用方法库,使用数字协议作为一般约束。

因此,我选择了数字协议作为Element类型以及T.Element的通用约束。尽管eelement都符合Numeric协议,但我无法将它们相乘(得到错误消息:无法将类型为'Element'的值(泛型结构'Vector'的泛型参数)转换为预期的参数类型“ T.Element”(协议“序列”的关联类型))。我该怎么办?

swift generics protocols numeric
2个回答
0
投票

如@Sweeper所述,您只能将相同的Numeric相乘。

所以您必须使用where子句在函数中指定它:

static func * <T: DArray> (lhs: Vector<Element>, rhs: T) -> Vector<Element> where T.Element == Element {
    let result = zip(lhs, rhs).map { lhs, rhs in
        lhs * rhs
    }
    return Vector(result)
}

0
投票

因为乘法是可交换的,所以将*的输出类型定义为操作数的任何一种都没有意义。相反,您应该允许所有DArray均使用其元素进行初始化。

protocol DArray: Sequence where Element: Numeric {
  var elements: [Element] { get set }
  init<Elements: Sequence>(_: Elements) where Elements.Element == Element
}

extension Vector {
  init<Elements: Sequence>(_ elements: Elements) where Elements.Element == Element {
    self.init( Array(elements) )
  }
}

然后,像这样定义运算符:

extension DArray {
  static func * <DArray1: DArray, Output: DArray>(
    dArray0: Self, dArray1: DArray1
  ) -> Output
  where DArray1.Element == Element, Output.Element == Element {
    .init( zip(dArray0, dArray1).map(*) )
  }
}

这样,您可以根据需要显式键入结果。

struct 🏹: DArray, IteratorProtocol {
  mutating func next() -> Int? { nil }

  var elements: [Element] = []

  init<Elements: Sequence>(_ elements: Elements) where Elements.Element == Element { }
}


( Vector() * 🏹([]) ) as Vector
( Vector() * 🏹([]) ) as 🏹
( 🏹([]) * Vector() ) as Vector
( 🏹([]) * Vector() ) as 🏹

let vector: Vector = ( Vector() * 🏹([]) )
let 💘: 🏹 = ( 🏹([]) * Vector() )
© www.soinside.com 2019 - 2024. All rights reserved.