<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class="">The Completing Generics Manifesto suggests a more universal solution with generic value parameters which is my vote:</div><div class=""><pre style="white-space: pre-wrap; font-variant-ligatures: normal; font-variant-position: normal; font-variant-numeric: normal; font-variant-alternates: normal; font-variant-east-asian: normal; line-height: normal; widows: 1;" class="">Generic value parameters
Currently, Swift’s generic parameters are always types. One could imagine allowing generic parameters that are values, e.g.,
struct MultiArray<T, let Dimensions: Int> { // specify the number of dimensions to the array
subscript (indices: Int...) -> T {
get {
require(indices.count == Dimensions)
// ...
}
}
A suitably general feature might allow us to express fixed-length array or vector types as a standard library component, and perhaps also allow one to implement a useful dimensional analysis library. Tackling this feature potentially means determining what it is for an expression to be a “constant expression” and diving into dependent-typing, hence the “maybe”.</pre></div><div class=""><br class=""></div>
> To better support interfacing with lower level systems, like graphics<br class="">> libraries for example, it would be helpful to support the concept of<br class="">> contiguous variables. The most common use case for this would be to create<br class="">> a Matrix struct that can be passed as data into something like Metal. This<br class="">> can be accomplished now, using something like the following:<br class="">> <br class="">> Current Option 1:<br class="">> <br class="">> struct Matrix2x2 {<br class="">> var m00: Float<br class="">> var m01: Float<br class="">> var m10: Float<br class="">> var m11: Float<br class="">> }<br class="">> <br class="">> OR<br class="">> Current Option 2:<br class="">> <br class="">> struct Matrix2x2 {<br class="">> var m: (Float, Float, Float, Float)<br class="">> }<br class="">> <br class="">> OR<br class="">> Current Option 3:<br class="">> <br class="">> struct Matrix2x2 {<br class="">> var m: [Float]<br class="">> }<br class="">> <br class="">> Options 1&2 allow for the compiler to enforce the fixed number of<br class="">> elements and also for the data to be easily passed into graphics libraries<br class="">> as their memory layout is somewhat predictable using sizeof, strideof, and<br class="">> alignof. The downside is that you lose the ability to easily subscript or<br class="">> iterate the elements.<br class="">> <br class="">> Option 3 does allow subscripting and iteration, but does not at compile<br class="">> time enforce a fixed number of elements and is not as easily passed into a<br class="">> library that expects to receive the raw data of the matrix.<br class="">> <br class="">> <br class="">> Contiguous Variables:<br class="">> <br class="">> struct Matrix2x2 {<br class="">> var m: Float:2*2<br class="">> }<br class="">> <br class="">> The variable `m` represents a series of 4 contiguous Float values. The<br class="">> specific number of values must be a compile time constant. The only needed<br class="">> functionality includes `count`, `subscript`, and iteration. To make things<br class="">> easier to implement and to help avoid confusion and more complex<br class="">> documentation, multiple dimensions are not allowed. To define multiple<br class="">> dimensions you must provide your own ordering by wrapping this type in<br class="">> another type and providing a custom subscript implementation. For example:<br class="">> <br class="">> struct RowMajorMatrix2x2 {<br class="">> var m: Float:2*2<br class="">> <br class="">> static let rows = 2<br class="">> static let columns = 2<br class="">> <br class="">> subscript(row: Int, column: Int) ->Float {<br class="">> return m[column * Matrix2x2.rows + row]<br class="">> }<br class="">> }<br class="">> <br class="">> sizeof(Matrix2x2) is 16<br class="">> strideof(Matrix2x2) is 16<br class="">> <br class="">> m.count is essentially a compile time constant and is not stored with the<br class="">> rest of the data but is available and can also be used to do runtime bounds<br class="">> checking.<br class="">> <br class="">> struct Vector3 {<br class="">> var v: Float:3<br class="">> }<br class="">> <br class="">> sizeof(Vector3) is 12<br class="">> strideof(Vector3) is 12<br class="">> <br class="">> C code should also now be able to expose data types that contain fixed<br class="">> sized arrays within them.<br class="">> <br class="">> <br class="">><span class="Apple-converted-space"> </span>
</body></html>