[swift-evolution] Proposal: Contiguous Variables (A.K.A. Fixed Sized Array Type)

Milos Rankovic milos at milos-and-slavica.net
Tue Apr 5 09:43:46 CDT 2016


This could potentially convert to Swift many library developers whose sanity depends on type guaranteed sequence sizes. I was just playing with Swift 2.2 along these lines, and got surprised how far I could get towards that ideal, see: http://codereview.stackexchange.com/q/124797/54297 <http://codereview.stackexchange.com/q/124797/54297> 

For example, I got this to compile:

    let v = Vector<__<_4,_2>,Int>(0)
    v.elements.count // 42

    let w = Vector<_3,Int>(0)
    w.elements // [0, 0, 0]
    w[2].value = 5

    for x in w {
        x // 0, 0, 5
    }

Once created, `v` and `w` here can never change size, not even from within the implementation.

milos

> On 4 Apr 2016, at 21:10, Brad Hilton via swift-evolution <swift-evolution at swift.org> wrote:
> 
> The Completing Generics Manifesto suggests a more universal solution with generic value parameters which is my vote:
> 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”.
> 
> > To better support interfacing with lower level systems, like graphics
> > libraries for example, it would be helpful to support the concept of
> > contiguous variables. The most common use case for this would be to create
> > a Matrix struct that can be passed as data into something like Metal. This
> > can be accomplished now, using something like the following:
> > 
> > Current Option 1:
> > 
> > struct Matrix2x2 {
> > var m00: Float
> > var m01: Float
> > var m10: Float
> > var m11: Float
> > }
> > 
> > OR
> > Current Option 2:
> > 
> > struct Matrix2x2 {
> > var m: (Float, Float, Float, Float)
> > }
> > 
> > OR
> > Current Option 3:
> > 
> > struct Matrix2x2 {
> > var m: [Float]
> > }
> > 
> > Options 1&2 allow for the compiler to enforce the fixed number of
> > elements and also for the data to be easily passed into graphics libraries
> > as their memory layout is somewhat predictable using sizeof, strideof, and
> > alignof. The downside is that you lose the ability to easily subscript or
> > iterate the elements.
> > 
> > Option 3 does allow subscripting and iteration, but does not at compile
> > time enforce a fixed number of elements and is not as easily passed into a
> > library that expects to receive the raw data of the matrix.
> > 
> > 
> > Contiguous Variables:
> > 
> > struct Matrix2x2 {
> > var m: Float:2*2
> > }
> > 
> > The variable `m` represents a series of 4 contiguous Float values. The
> > specific number of values must be a compile time constant. The only needed
> > functionality includes `count`, `subscript`, and iteration. To make things
> > easier to implement and to help avoid confusion and more complex
> > documentation, multiple dimensions are not allowed. To define multiple
> > dimensions you must provide your own ordering by wrapping this type in
> > another type and providing a custom subscript implementation. For example:
> > 
> > struct RowMajorMatrix2x2 {
> > var m: Float:2*2
> > 
> > static let rows = 2
> > static let columns = 2
> > 
> > subscript(row: Int, column: Int) ->Float {
> > return m[column * Matrix2x2.rows + row]
> > }
> > }
> > 
> > sizeof(Matrix2x2) is 16
> > strideof(Matrix2x2) is 16
> > 
> > m.count is essentially a compile time constant and is not stored with the
> > rest of the data but is available and can also be used to do runtime bounds
> > checking.
> > 
> > struct Vector3 {
> > var v: Float:3
> > }
> > 
> > sizeof(Vector3) is 12
> > strideof(Vector3) is 12
> > 
> > C code should also now be able to expose data types that contain fixed
> > sized arrays within them.
> > 
> > 
> > 
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160405/68447df0/attachment.html>


More information about the swift-evolution mailing list