Swift: 两个数字相乘
Swift: Multiply two Numerics
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
协议,文档说:
The Numeric protocol provides a suitable basis for arithmetic on
scalar values, such as integers and floating-point numbers. You can
write generic methods that operate on any numeric type in the standard
library by using the Numeric protocol as a generic constraint.
所以我选择数字协议作为元素类型和 T.Element 的通用约束。尽管 e
和 element
都符合 Numeric
协议,但我无法将它们相乘(收到错误消息:无法转换 'Element' 类型的值(通用结构 'Vector') 的通用参数到预期参数类型 'T.Element'(协议的关联类型 'Sequence'))。我该怎么做?
正如@Sweeper 提到的,您只能乘以相同的 Numeric
s。
因此您必须在函数中使用 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)
}
因为乘法是可交换的,所以将 *
的输出类型定义为任一操作数类型是没有意义的。相反,您可以允许所有 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 * <Parameter1: DArray, Output: DArray>(
dArray0: Self, dArray1: Parameter1
) -> Output
where Parameter1.Element == Element, Output.Element == Element {
multiply(dArray0, dArray1)
}
static func * (dArray0: Self, dArray1: Self) -> Self {
multiply(dArray0, dArray1)
}
private static func multiply<Parameter0: DArray, Parameter1: DArray, Output: DArray>(
_ dArray0: Parameter0, _ dArray1: Parameter1
) -> Output
where Parameter0.Element == Parameter1.Element, Parameter1.Element == Output.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() )
Vector([1]) * Vector()
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
协议,文档说:
The Numeric protocol provides a suitable basis for arithmetic on scalar values, such as integers and floating-point numbers. You can write generic methods that operate on any numeric type in the standard library by using the Numeric protocol as a generic constraint.
所以我选择数字协议作为元素类型和 T.Element 的通用约束。尽管 e
和 element
都符合 Numeric
协议,但我无法将它们相乘(收到错误消息:无法转换 'Element' 类型的值(通用结构 'Vector') 的通用参数到预期参数类型 'T.Element'(协议的关联类型 'Sequence'))。我该怎么做?
正如@Sweeper 提到的,您只能乘以相同的 Numeric
s。
因此您必须在函数中使用 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)
}
因为乘法是可交换的,所以将 *
的输出类型定义为任一操作数类型是没有意义的。相反,您可以允许所有 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 * <Parameter1: DArray, Output: DArray>(
dArray0: Self, dArray1: Parameter1
) -> Output
where Parameter1.Element == Element, Output.Element == Element {
multiply(dArray0, dArray1)
}
static func * (dArray0: Self, dArray1: Self) -> Self {
multiply(dArray0, dArray1)
}
private static func multiply<Parameter0: DArray, Parameter1: DArray, Output: DArray>(
_ dArray0: Parameter0, _ dArray1: Parameter1
) -> Output
where Parameter0.Element == Parameter1.Element, Parameter1.Element == Output.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() )
Vector([1]) * Vector()