At times when your types hold numeric values, you may want to perform arithmetic operations on them. Take for instance a Vector2D
type that holds two Double
values.
struct Vector2D {
var x: Double
var y: Double
}
To add another vector to it, you can implement a method add(_:)
that adds the corresponding values of the two vectors. Similarly, to subtract another vector, you can implement a method subtract(_:)
.
extension Vector2D {
mutating func add(_ other: Vector2D) {
x += other.x
y += other.y
}
mutating func subtract(_ other: Vector2D) {
x -= other.x
y -= other.y
}
}
To use these methods, you would write code like this:
var vector1 = Vector2D(x: 1, y: 2)
let vector2 = Vector2D(x: 3, y: 4)
vector1.add(vector2)
print(vector1) // Vector2D(x: 4.0, y: 6.0)
vector1.subtract(vector2)
print(vector1) // Vector2D(x: 1.0, y: 2.0)
This works well, but it can be made more elegant. Swift provides a protocol AdditiveArithmetic
that can be used to define the addition and subtraction operations on your types.
AdditiveArithmetic Protocol
The AdditiveArithmetic
protocol requires the conforming type to implement the following properties and methods:
// An value that represents zero.
static var zero: Self { get }
// A method that adds two values and returns the result.
static func + (lhs: Self, rhs: Self) -> Self
// A method that subtracts two values and returns the result.
static func - (lhs: Self, rhs: Self) -> Self
By conforming to this protocol, you can define the addition and subtraction operations on your types. Additional operators like +=
and -=
are also made available for types conforming to the AdditiveArithmetic
protocol.
// A method that returns the current value unchanged.
static func + (x: Self) -> Self
// A method that adds the right-hand value to the left-hand value and stores the result in the left-hand value.
static func += (lhs: inout Self, rhs: Self)
// A method that subtracts the right-hand value from the left-hand value and stores the result in the left-hand value.
static func -= (lhs: inout Self, rhs: Self)
Let’s make the Vector2D
type conform to the AdditiveArithmetic
protocol.
extension Vector2D: AdditiveArithmetic {
static var zero: Vector2D {
Vector2D(x: 0, y: 0)
}
static func + (lhs: Vector2D, rhs: Vector2D) -> Vector2D {
Vector2D(x: lhs.x + rhs.x, y: lhs.y + rhs.y)
}
static func - (lhs: Vector2D, rhs: Vector2D) -> Vector2D {
Vector2D(x: lhs.x - rhs.x, y: lhs.y - rhs.y)
}
}
With this implementation, you can now use the +
and -
operators to add and subtract vectors.
var vector1 = Vector2D(x: 1, y: 2)
let vector2 = Vector2D(x: 3, y: 4)
vector1 += vector2
print(vector1) // Vector2D(x: 4.0, y: 6.0)
vector1 -= vector2
print(vector1) // Vector2D(x: 1.0, y: 2.0)
let vector3 = vector1 + vector2
print(vector3) // Vector2D(x: 4.0, y: 6.0)
let vector4 = vector1 - vector2
print(vector4) // Vector2D(x: -2.0, y: -2.0)
let vector5 = Vector2D.zero
print(vector5) // Vector2D(x: 0.0, y: 0.0)
let vector6 = Vector2D.zero - vector1
print(vector6) // Vector2D(x: -1.0, y: -2.0)
Another operator to complement this protocol is the unary minus operator -
. This operator negates the values.
// A method that returns the negated value.
static func - (x: Self) -> Self
We can implement this operator for the Vector2D
type like this:
extension Vector2D {
static prefix func - (vector: Vector2D) -> Vector2D {
Vector2D(x: -vector.x, y: -vector.y)
}
}
The unary minus operator can be used like this:
let vector7 = -vector1
print(vector7) // Vector2D(x: -1.0, y: -2.0)
By conforming to the AdditiveArithmetic
protocol, you can make your types more expressive and elegant when dealing with arithmetic operations.
Although the AdditiveArithmetic
protocol is primarily used for numeric types, you can also use it for other types that support addition and subtraction operations, or for types that can leverage the +
and -
operators in a non-numeric context.
Types conforming to the AdditiveArithmetic
protocol can be leveraged in operations that require addition and subtraction, such as in collections that support element-wise addition and subtraction.
extension Sequence where Element: AdditiveArithmetic {
func sum() -> Element {
return reduce(.zero, +)
}
}
let numbers = [1, 2, 3, 4, 5]
let total = numbers.sum()
print(total) // 15
let vectors = [Vector2D(x: 1, y: 2), Vector2D(x: 3, y: 4), Vector2D(x: 5, y: 6)]
let sumVector = vectors.sum()
print(sumVector) // Vector2D(x: 9.0, y: 12.0)
The sum()
method can now be used with any collection of elements that conform to the AdditiveArithmetic
protocol.
In this article, you learned how to use the AdditiveArithmetic
protocol in Swift to define addition and subtraction operations on your types. By conforming to this protocol, you can make your types more expressive and elegant when dealing with arithmetic operations.
To check out the official documentation on the AdditiveArithmetic
protocol, visit AdditiveArithmetic | Apple Developer Documentation.