I have a struct that stores a variety of measurements, and the accuracy of measurements (i.e. 10 cm ± 2 cm). Not all measurements are necessarily measuring the same thing (angle, length, speed, etc.) Is there a best practice for storing such information? I started with:
struct Example {
let x: Double
let xAccuracy: Double
let y: CGPoint
let yAccuracy: Double // radius around y
let z: Int
let zAccuracy: Int
}
It feels off to have two fields for every property. I'm considering something like this:
struct ApproximateValue<Value, Accuracy> {
let value: Value
let accuracy: Accuracy
}
struct Example2 {
let x: ApproximateValue<Double, Double>
let y: ApproximateValue<CGPoint, Double>
let z: ApproximateValue<Int, Int>
}
A simple struct is probably good. You might want to also check out the Measurements framework available in Foundation if you want to keep track of the units being stored.
let a = Measurement(value: 3, unit: UnitLength.meters)
let b = Measurement(value: 3, unit: UnitLength.feet)
let c = a + b
c.value // will get the value in meters
You can use it with your ApproximateValue abstraction. You might want to make some typealias to improve the common cases for your problem domain.
struct ApproximateValue<Value, Accuracy> {
var value: Value
var accuracy: Accuracy
}
typealias Length = ApproximateValue<Measurement<UnitLength>,
Measurement<UnitLength>>
typealias Point = ApproximateValue<CGPoint, Double>
typealias QuantizedThing = ApproximateValue<Int, Int>
struct Example3 {
var x: Length
var y: Point
var z: QuantizedThing
}
let x3 = Example3(x: .init(value: c, accuracy: b),
y: .init(value: .zero, accuracy: 0.2),
z: .init(value: 10, accuracy: 1))
The way that I like to approach problems in Swift is to build up a little kingdom of abstractions and then solve the problem at hand simply with that.
As a side note, you probably want to declare your struct properties var since you can declare the struct let and make everything immutable if you need to.