We've been experimenting with synthesizing conformances to AdditiveArithmetic
(and other protocols) as part of differentiable programming in Swift, and we'd like to start pitching these through Swift Evolution.
AdditiveArithmetic
generalizes types that define addition, subtraction, and a zero. Conforming types include both numeric scalar types, like Int
and Float
, as well as vector types like SIMD4<Double>
(this is not implemented yet because of ABI concerns).
Similar to Equatable
and Hashable
synthesis, AdditiveArithmetic
conformance synthesis for structs works when all stored properties conform to AdditiveArithmetic
.
struct Point<T: AdditiveArithmetic>: @memberwise AdditiveArithmetic {
var x, y: T
// Compiler synthesizes:
static var zero: Point {
return Point(x: T.zero, y: T.zero)
}
static func + (lhs: Point, rhs: Point) -> Point {
return Point(x: lhs.x + rhs.x, y: rhs.y + rhs.y)
}
static func - (lhs: Point, rhs: Point) -> Point {
return Point(x: lhs.x - rhs.x, y: rhs.y - rhs.y)
}
static func += (lhs: inout Point, rhs: Point) {
lhs.x += rhs.x
lhs.y += rhs.y
}
static func -= (lhs: inout Point, rhs: Point) {
lhs.x -= rhs.x
lhs.y -= rhs.y
}
}
var point = Point<Float>(x: 2, y: 3)
print(point + point) // Point<Float>(x: 4.0, y: 6.0)
print(Point<Float>.zero) // Point<Float>(x: 0.0, y: 0.0)
We believe AdditiveArithmetic
conformance synthesis is important for numerical computing: it makes aggregates of numeric scalars or vectors just work with addition. Currently, it’s an important usability feature for differentiable programming in Swift.
Edit: As some have pointed out, memberwise derivation of AdditiveArithmetic
doesn't make sense as a default implementation in all cases, unlike Equatable
and Hashable
synthesis. Thus, derivation is gated by the @memberwise
attribute.
Feedback is welcome!