[swift-evolution] Yet another fixed-size array spitball session

Rien Rien at Balancingrock.nl
Mon May 29 02:37:21 CDT 2017

While I’d like a fixed size array, I’d agree with Rod that this looks odd.

Myself I use the name ‘array’ a lot in places where I get/need a temporary array that lives for a few lines only. So I am against using the keyword ‘array’.

A name like SizedArray would seem more in-line with other Swift types.

Also, there is a standard way of looking up indicies, and it uses the ‘[]’ signs. Why did you drop that?
I would expect confusion when looking up a variable index like: let c = x.myIndex
let c = x[myIndex] looks decidedly more clear to me.

Btw, what to think of:

var z: array 2 of Array<array 5 of Double>

(that looks pretty horrible to me)


Site: http://balancingrock.nl
Blog: http://swiftrien.blogspot.com
Github: http://github.com/Balancingrock
Project: http://swiftfire.nl - A server for websites build in Swift

> On 29 May 2017, at 08:37, Daryle Walker via swift-evolution <swift-evolution at swift.org> wrote:
> Static-Sized Arrays
> This is a new proposed syntax for handling array types whose size is fixed at compile time. This is a classic kind of type that's still missing in Swift.
> Like the built-in processor numeric types are mapped to special struct types, any built-in vector types should be mapped to special array types. There should be some sort of construct to allow parallel visitation of elements.
> For a given array type A with an element type B, we have strideof(A) == COUNT * strideof(B), where COUNT is the number of elements in the array, which is the product of the lengths along each dimension. (A zero-dimension array has an element count of one.)
> New Keywords
> 	• array
> 	• of
> These keywords should be conditional if possible. The of shouldn't appear without following an array, so of should be easy to make conditional.
> Immediate Arrays
> Immediate arrays are a new kind of compound type. They have value semantics.
> let x: array 3 of Int = [1, 2, 3]
> var y: array 2 of array 5 of Double
> Hopefully, this is simpler than my last proposal. I'm thinking that "array" is like a verb here.
> The element type is at the end, so no parentheses (or similar) are needed. The syntax is easy to expand for nested array types. Here, the extents go from the widest span to the narrowest, like nested arrays in C. The inner element type is at the end instead of the start.
> assert(x.0 == 1)
> x.3 = 3  // ERROR!
> y.1.3 = 3
> y.0 = [-3, -2, -1, 0, +1]
> Elements are addressed just like in tuples.
> Nominal Arrays
> Nominal arrays are a new kind of named type. They have value semantics.
> array MyArray: (0..<6) of Int {
>     /* ... */
> }
> I'm thinking "array" is like an adjective (or noun) here. The base-and-protocol list must have a shape specifier as its first item.
> shape-specifier → ( extents-list_opt ) of type
> extents-list → extent
> extents-list → extent , extents-list
> extent → type storage-rank_opt
> extent → expression ..< expression storage-rank_opt
> extent → expression ... expression storage-rank_opt
> storage-rank → : expression
> A type used for an extent:
> 	• Must be a raw-value enumeration type.
> 	• The raw-value type must be one of the default integer types.
> 	• There must be at least one case, and all the cases must form a contiguous range of values.
> A range used for an extent:
> 	• Must use for its boundary type either:
> 		• a default integer type, or
> 		• an enumeration type that could qualify as an extent type.
> 	• Must be a valid range with at least one element.
> The expression for a storage rank must evaluate to a compile-time integer value that is at least zero and less than the number of extents. An extent without an explicit storage rank gets one equal to the smallest valid value yet unused. (Multiple extents without explicit ranks are finalized in lexical order.)
> The extent with the largest storage rank has elements with adjacent indexes (assuming all other extents use fixed indexes) placed adjacent in memory. The extent with storage rank 0 have elements with adjacent indexes (assuming all other extents use fixed indexes) the furthest span apart in memory.
> The total number of elements for the array is the product of the lengths of the extents. A zero-dimension array has a singular element.
> A nominal array type can have type-level members and computed instance-level properties, just like the other named types. The initial set of members, if not overridden, are:
> 	• A type-alias Element that refers to the element type.
> 	• A type-alias Index that refers to a tuple composed of the extent types. For a range-based extent, the corresponding type is its boundary type.
> 	• If the element type is default-initializable, a default initializer.
> 	• An initializer that takes as its only parameter an Element, which is copied to each element.
> 	• An initializer that takes as its only parameter a closure that takes as its only parameter an Index and returns the value the corresponding element starts with.
> 	• An initializer similar to the previous, but the closure takes the index tuple's parameters separately.
> 	• Two subscript members, with get and set modes, to handle dereferencing. One member takes an Index, the other an exploded index list. It's an error to refer to an invalid index location.
> Flexible Array Reference
> To not have to fix a function for each extent shape, something similar to the old T[] array segment idea from C(++) is needed:
> func foo(x: array of Int) -> Int
> func bar(y: array of mutating Double) -> Int
> Without a size given inside the array declaration, these functions can work with any array with the given element type. Array-segment references are reference types.
> An array-segment reference conforms to RandomAccessCollection. A reference that is marked mutating also conforms to MutableCollection. (Should we create a new mutable keyword instead?)
> A function that returns or otherwise writes out an array-segment reference must ensure it points to memory that will survive the function's end. (I'm not sure we should enforce some sort of retain/ARC instead.) (Should we ban these instead?)
> An array-segment reference can be generated from an immediate array or a nominal array using as. A reference can be mutatingif the source array starts in var mode. Array-segment references access their elements in storage order.
> Conversions
> These conversions can work through as:
> 	• array N of T → array of T
> 	• array N of T → array of mutating T, if the source array was in var mode
> 	• array N of T → array M * N of U, when T is an array M of U
> 	• MyArray → array of MyArray.Element
> 	• MyArray → array of mutating MyArray.Element, if the source array was in var mode.
> 	• array of mutating T → array of T
> 	• array of T → array of U, where U is the element type of T
> 	• array of mutating T → array of mutating U, where U is the element type of T
> Any conversion that requires a chain of these is also legal. When a function has an array-segment reference as a parameter, and the argument is an array with the same element type, the argument doesn't need an explicit as.
> (Should we allow the reverse-direction transformations, or even chains of them, with "as!" and/or "as?"? Note that this could end up converting an array 5 of Int to an array 3 of array 2 of Int with its last Int nested element invalid.)
> Parallel/Vector Processing (only semi-serious)
> As the processor's built-in numeric types are mapped to the default numeric types, we should do something similar for a processor's built-in vector numeric types. Like a processor that has four integers as a vector, we could define a Int_4 structure type that maps to it.
> We also need a way to possibly do evaluations in parallel. What about:
> do x, y, z as array {
>     z = x == y
>     x += y
> }
> The three objects between do and as have to have the same shape. Within the block, the object names now refer to corresponding individual elements.
> Extra Traits
> As I was writing this, I came up with new functionality and corresponding keywords. Should we have an #extentsof(type)to use an extent shape from one nominal array type to another? Should we have an #extentscount(type)?
> Example: take the do as array block. If x and y were function parameters, but z was an internal object, how would we define z besides manually copying the shape list?
>> Daryle Walker
> Mac, Internet, and Video Game Junkie
> darylew AT mac DOT com 
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

More information about the swift-evolution mailing list