I'm working on a linear algebra package that relies on Accelerate, BLAS, and LAPACK for performing vector and matrix operations. Consequently, most of the operations use functions that are only applicable to a certain value type such as Float or Double. This makes for a lot of redundant DocC documentation comments because I need to provide documentation for each function for that specific type. The example below demonstrates this.
Here is a generic vector structure that uses a flat array as the underlying value storage.
// Vector.swift
struct Vector<T> {
let size: Int
var values: [T]
init(_ values: [T]) {
self.size = values.count
self.values = values
}
init(like vector: Vector) {
self.size = vector.size
self.values = vector.values
}
}
The code below uses the vector struct to perform element-wise vector addition for Int, Float, and Double values. The Accelerate vDSP.add
function only supports Float and Double values so a loop is used for vectors that contain Int values. Notice the documentation comments are basically the same for each add
function. Ideally, I would like to write just one set of documentation comments for all three add
functions. But I'm not aware of any DocC features that allow you to provide a single set of documentation comments for different value types.
// Addition.swift
import Accelerate
/// Add two vectors using integer values.
/// - Parameters:
/// - a: The first vector.
/// - b: The second vector.
/// - Returns: The result vector.
func add(_ a: Vector<Int>, _ b: Vector<Int>) -> Vector<Int> {
var result = [Int](repeating: 0, count: a.size)
for i in 0..<a.size {
result[i] = a.values[i] + b.values[i]
}
return Vector(result)
}
/// Add two vectors using single-precision values.
/// - Parameters:
/// - a: The first vector.
/// - b: The second vector.
/// - Returns: The result vector.
func add(_ a: Vector<Float>, _ b: Vector<Float>) -> Vector<Float> {
var vec = Vector(like: a)
vDSP.add(a.values, b.values, result: &vec.values)
return vec
}
/// Add two vectors using double-precision values.
/// - Parameters:
/// - a: The first vector.
/// - b: The second vector.
/// - Returns: The result vector.
func add(_ a: Vector<Double>, _ b: Vector<Double>) -> Vector<Double> {
var vec = Vector(like: a)
vDSP.add(a.values, b.values, result: &vec.values)
return vec
}
The only solution (that I know of) to reduce this redundant documentation is to use a protocol for the generic values. For example, I can define a scalar protocol as follows:
// Scalar.swift
protocol Scalar {
static func add(_ a: Vector<Self>, _ b: Vector<Self>) -> Vector<Self>
}
extension Int: Scalar { }
extension Float: Scalar { }
extension Double: Scalar { }
Using this protocol I can extend the Int, Float, and Double types with the add
function for that particular type. This allows me to have one public add
function and therefore one set of documentation comments which applies to all the supported types. This approach requires more code but the amount of documentation comments is greatly reduced.
// Addition.swift
import Accelerate
extension Int {
static func add(_ a: Vector<Self>, _ b: Vector<Self>) -> Vector<Self> {
var result = [Int](repeating: 0, count: a.size)
for i in 0..<a.size {
result[i] = a.values[i] + b.values[i]
}
return Vector(result)
}
}
extension Float {
static func add(_ a: Vector<Self>, _ b: Vector<Self>) -> Vector<Self> {
var vec = Vector(like: a)
vDSP.add(a.values, b.values, result: &vec.values)
return vec
}
}
extension Double {
static func add(_ a: Vector<Self>, _ b: Vector<Self>) -> Vector<Self> {
var vec = Vector(like: a)
vDSP.add(a.values, b.values, result: &vec.values)
return vec
}
}
/// Calculate the element-wise addition of two vectors with integer, float, or double values.
/// - Parameters:
/// - a: The first vector.
/// - b: The second vector.
/// - Returns: The result of adding two vectors.
func add<T>(_ a: Vector<T>, _ b: Vector<T>) -> Vector<T> where T: Scalar {
T.add(a, b)
}
Is this is a reasonable approach to reduce the amount of documentation needed for different value types? Or does DocC provide some feature where I can provide one set of documentation for many value types? Are there any performance issues that I should be aware of when using the protocol approach compared to the non-protocol approach?