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

Haravikk swift-evolution at haravikk.me
Fri Jun 2 05:51:09 CDT 2017


> On 2 Jun 2017, at 07:38, Robert Bennett <rltbennett at icloud.com> wrote:
> 
> My favorite proposal so far is one that was posted a while ago, [Int * 4]. I think that this syntax looks pretty Swifty. There isn't an oddball subscript operator like with Int[4], and there isn't a need to allow generics to support values as parameters. It's clear that [Int * 4] will be array-like and contain four Ints. For multidimensional arrays we could use [Int * (2,3)]. For an array of tuples, [(x: Int, y: Int) * 4]. I'm not sure why nested static arrays would be needed when multidimentionality is provided out of the box, but presumably the syntax would support them; you would just need to subscript the arrays one at a time instead of with a single subscript operator, e.g., a[i][j] instead of a[i, j].
> 
> I'm imagining this syntax working like [T] does now as a shorthand for Array<T>, although I'm not sure what [Int * 4] should be short for (StaticArray<Int, 4>? Vector4<Int>? ...). Constructors for static arrays would be called using [Int * 4](args). I'm thinking the constructors would be [T * 4](filledWith: T), [T * 4](filledBy: (Int)->T), and an initializer taking a Sequence that fails in some manner on a dimension mismatch.

Even with that syntax I'd say there should be a means of handling it in a general purpose way.

For example, let's say you defined that syntax as an operator:

	func * <T>(lhs: T.self, rhs: Int) -> (type: T.self, size:Int) { return (type: lhs, size: rhs) }

Now you have an explicit tuple describing what it is you want to do, which the compiler can now pass to a type during compilation to do with as it pleases. In this case it would pass to some FixedArray type which can use the type and size to optimise itself. Not sure on the specifics of how just yet, but point being to try to make this a part of the language that others can use, rather than simply being some form of compiler magic.

My reasoning being that it may be useful to have other type operators in future, and/or other types able to take and use the same information.


For example, I briefly discussed once the possibility of a Float variant whose compatibility would be limited by its target precision, and use ± as an operator so that I could define for example:

	var a:Float±0.1 = 0.5
	var b:Float±0.5 = 5.0
	a = b // error; precision mismatch (b's precision is too low to guarantee accuracy)
	b = a // this is fine, as a is "more precise" than b


Now put aside whether that idea is actually useful or not; my point is that I'd like support for fixed-size arrays to be general purpose, as there are other possible uses for the same basic capabilities (i.e- type variables).

The key thing really is that we need some way for the compiler to recognise that a type is being refined somehow, and compile it separately as appropriate. I mentioned generics style variable passing because to me this is the most logical way to pass information into a type, not because I want it to be the default syntax at the call site; I fully support other shorthands for the actual passing of data, the key for me is being able to leverage the same kind of type-refining capabilities in my own types, rather than this whole thing just being focused solely on fixed-sized arrays implemented with compiler magic.

> On Jun 1, 2017, at 7:36 AM, Haravikk via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
> 
>> Just wanted to add my two-cents to this discussion, but in terms of syntax I think that the basic method for specifying size should be with some kind of type variables, like so:
>> 
>> 	struct MyFixedArray<T, size:Int> { … }
>> 
>> The idea being that we can then use size as a variable anywhere within the code for MyFixedArray, but unlike other variables it is determined at compile time, so should be optimised accordingly. As with generics, setting a type variable effectively creates a variant type so for example, a MyFixedArray<Int, size:3> and a MyFixedArray<Int, size:4> would no longer be directly compatible as they may differ internally.
>> 
>> This would be useful not just for fixed arrays, but other possibly type variations as well. Ideally it should be possible to specify a default value for type variables; while this wouldn't be useful for fixed arrays, it may be useful for other type variants.
>> 
>> To better suit the specific use-case of arrays, we could also add some useful attributes or keywords, for example, reusing subscript could give us:
>> 
>> struct MyFixedArray<T, subscript size:Int> { … }
>> let foo:MyFixedArray[4] = [1, 2, 3, 4] // with T being inferred, this is a shorthand for specifying a size of 4
>> 
>> Type variables could also be usable with generics, like-so:
>> 
>> // only accept fixed arrays of same or smaller size:
>> func myMethod<FA>(values:FA) where FA:FixedArray, FA.size <= Self.size { … } 
>> 
>> These are the kind of general purpose capabilities I'd like to see at some point, as the usefulness extends beyond just fixed-size arrays.
>> 
>> 
>> 
>> However, on the  subject of fixed-size arrays specifically, one other possibility to explore is the concept of Tuple repetition and subscripting. For example, it would be interesting if we could do things like:
>> 
>> 	var foo:(Int)[4] = 0 // Initialises four Ints, all set initially to zero
>> 	for i in 0 ..< 4 { foo[i] = i } // values are no 0, 1, 2, 3
>> 
>> This can be especially interesting when you get into more complex tuples like so:
>> 
>> 	var bar:(x:Int, y:Int)[10] = (x: 0, y: 0) // Initialises 10 pairs of Ints, all initially set to zero
>> 	for i in 0 ..< 10 { bar[i].x = i; bar[i].y = i } // here we need to use .x and .y to access the values of each pair
>> 
>> Of course this would have the same performance characteristics as standard tuples, but it's an interesting means for creating quick, fixed-size arrays in a flexible way. Part of the idea here is that by subscripting tuples, we avoid the need for a general subscript on all types, keeping that available for use-cases like the above.
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution at swift.org <mailto:swift-evolution at swift.org>
>> https://lists.swift.org/mailman/listinfo/swift-evolution <https://lists.swift.org/mailman/listinfo/swift-evolution>

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170602/6e376eb9/attachment.html>


More information about the swift-evolution mailing list