[Pitch] New Version of Array Proposal

To be clearer, I'm not claiming that we should implement FSAs as tuples, just pointing out that it might be a pretty easy option if certain other proposals were to be accepted. IMHO, it seems premature to put a ton of time & effort into a FSA proposal now when there'll likely be a proposals for pretty much all the pieces required for the tuple-based approach as soon as these larger topics become in-scope. Even if we decide tuples aren't appropriate for FSAs (and again, I'm not arguing for or against that approach here), it seems likely to me that we'd want to design these features roughly together so that we can ensure that their syntaxes don't get in each others' ways and everything still feels right together for the direction Swift as a whole is going.

For example, the `ArrayStats` type in this proposal seems like it's mostly there as a work-around for Swift's current lack of Variadic Generics. Given that that's a feature we're likely to get at some point (hopefully in Swift 4.1 or 5, but we'll have to see what's in-scope), and that we don't want to support superfluous bits of code hanging around the stdlib or compiler (or language spec, since we're talking about a bunch of new grammar rules, too), and that we really don't want to break source compatibility later, doesn't it make sense to work on Variadic Generics first and see how that informs what we want to do WRT FSAs?

- Dave Sweeris

···

On Jul 23, 2017, at 2:49 PM, David Sweeris via swift-evolution <swift-evolution@swift.org> wrote:

On Jul 23, 2017, at 12:18, Taylor Swift <kelvin13ma@gmail.com <mailto:kelvin13ma@gmail.com>> wrote:

On Sun, Jul 23, 2017 at 2:21 PM, David Sweeris <davesweeris@mac.com <mailto:davesweeris@mac.com>> wrote:

On Jul 23, 2017, at 09:08, Taylor Swift <kelvin13ma@gmail.com <mailto:kelvin13ma@gmail.com>> wrote:

Speaking of which, IIRC, at one point we were considering adding subscripts to tuples and using that for FSAs. I think the hangups were pretty much just that tuples can't conform to protocols and the iffy semantics of subscripting heterogeneous tuples. The former is a bit of a pain point anyway, and unless I've forgotten about some deal-breaker that was brought up in one of those threads, I think it's somewhat likely that we'll eventually do something about it. Unrelated to FSAs and subscripting tuples, we've also discussed variadic generic arguments... My recollection is that there was broad support for the idea; it's just a matter of it being in-scope so that we can figure out the syntax. Once we get that done, if we make tuples extendable we could just say (hand-wavey straw-man syntax, of course):
    extension (Ts: _...) where Ts.count > 0, Ts.reduce(true) { $0 = Ts.Head.self == $1.self } == true {
        subscript(_ i: Int) -> Ts.Head {...}
    }

... and just do it all through tuples. Is this a better than having a dedicated FSA type? Dunno. In large part, it depends on how difficult the various ideas will be to implement, and how useful the extra bits of functionality would be to the rest of the language. Unfortunately, the people who have those answers are busy working with the Swift 4.0 release, and likely don't have time to really weigh in on out of scope topics (which we all agree can be frustrating, but there are practical realities in life, and staying focused enough to meet deadlines is one of theirs).

I don’t think tuples are a suitable replacement for FSAs. A tuple should be able to be broken up and optimized by the compiler, and have no contiguity guarantees in memory.

C's static arrays are imported as tuples, which need at least some level of contiguity guarantees to work. Even if tuples in general make that such a guarantee, tuple-based FSAs could use the same compiler logic as imported C arrays.

To be clearer, I'm not claiming that we should implement FSAs as tuples, just pointing out that it might be a pretty easy option if certain other proposals were to be accepted. IMHO, it seems premature to put a ton of time & effort into a FSA proposal now when there'll likely be a proposals for pretty much all the pieces required for the tuple-based approach as soon as these larger topics become in-scope. Even if we decide tuples aren't appropriate for FSAs (and again, I'm not arguing for or against that approach here), it seems likely to me that we'd want to design these features roughly together so that we can ensure that their syntaxes don't get in each others' ways and everything still feels right together for the direction Swift as a whole is going.

For example, the `ArrayStats` type in this proposal seems like it's mostly there as a work-around for Swift's current lack of Variadic Generics. Given that that's a feature we're likely to get at some point (hopefully in Swift 4.1 or 5, but we'll have to see what's in-scope), and that we don't want to support superfluous bits of code hanging around the stdlib or compiler (or language spec, since we're talking about a bunch of new grammar rules, too), and that we really don't want to break source compatibility later, doesn't it make sense to work on Variadic Generics first and see how that informs what we want to do WRT FSAs?

- Dave Sweeris

···

On Jul 23, 2017, at 2:49 PM, David Sweeris via swift-evolution <swift-evolution@swift.org> wrote:

On Jul 23, 2017, at 12:18, Taylor Swift <kelvin13ma@gmail.com <mailto:kelvin13ma@gmail.com>> wrote:

Speaking of which, IIRC, at one point we were considering adding subscripts to tuples and using that for FSAs. I think the hangups were pretty much just that tuples can't conform to protocols and the iffy semantics of subscripting heterogeneous tuples. The former is a bit of a pain point anyway, and unless I've forgotten about some deal-breaker that was brought up in one of those threads, I think it's somewhat likely that we'll eventually do something about it. Unrelated to FSAs and subscripting tuples, we've also discussed variadic generic arguments... My recollection is that there was broad support for the idea; it's just a matter of it being in-scope so that we can figure out the syntax. Once we get that done, if we make tuples extendable we could just say (hand-wavey straw-man syntax, of course):
    extension (Ts: _...) where Ts.count > 0, Ts.reduce(true) { $0 = Ts.Head.self == $1.self } == true {
        subscript(_ i: Int) -> Ts.Head {...}
    }

... and just do it all through tuples. Is this a better than having a dedicated FSA type? Dunno. In large part, it depends on how difficult the various ideas will be to implement, and how useful the extra bits of functionality would be to the rest of the language. Unfortunately, the people who have those answers are busy working with the Swift 4.0 release, and likely don't have time to really weigh in on out of scope topics (which we all agree can be frustrating, but there are practical realities in life, and staying focused enough to meet deadlines is one of theirs).

I don’t think tuples are a suitable replacement for FSAs. A tuple should be able to be broken up and optimized by the compiler, and have no contiguity guarantees in memory.

C's static arrays are imported as tuples, which need at least some level of contiguity guarantees to work. Even if tuples in general make that such a guarantee, tuple-based FSAs could use the same compiler logic as imported C arrays.

I think I mentioned it at the end of the proposal, but there’s a reason I’m using comma/colon/semicolon for FSAs. They are already reserved separators within Swift’s syntax. The multiplier ideas or “of” seem to be just for cuteness; why take a token out from being free to reserved for a purpose that can be mechanically done by an existing separator token.

···

On Jul 23, 2017, at 3:18 PM, Taylor Swift via swift-evolution <swift-evolution@swift.org> wrote:

If we’re actually going to try and establish a relationship between the FSA asterisk and the multiplication asterisk, this is even more problematic. How does the asterisk work in FSA literals, where there is no type annotation to go on the right of the asterisk?

Also introducing contextual keywords like “of” is going to cause a huge amount of problems with syntax highlighters considering how often the word “of” is used as an argument label in Swift. The words “as” and “stride” already make for some interesting code highlighting, “of” would take it to a whole new level.


Daryle Walker
Mac, Internet, and Video Game Junkie
darylew AT mac DOT com

I think that’s supposed to be a workaround solution, not a map going forward. By having to support C-array conversion, tuples have to give up tuple-specific optimizations, like rearranging members and contiguity. Adding FSAs (with a distinct internal representation) will let the two have different optimizations.

···

On Jul 23, 2017, at 5:49 PM, David Sweeris via swift-evolution <swift-evolution@swift.org> wrote:

On Jul 23, 2017, at 12:18, Taylor Swift <kelvin13ma@gmail.com <mailto:kelvin13ma@gmail.com>> wrote:

I don’t think tuples are a suitable replacement for FSAs. A tuple should be able to be broken up and optimized by the compiler, and have no contiguity guarantees in memory.

C's static arrays are imported as tuples, which need at least some level of contiguity guarantees to work. Even if tuples in general make that such a guarantee, tuple-based FSAs could use the same compiler logic as imported C arrays.


Daryle Walker
Mac, Internet, and Video Game Junkie
darylew AT mac DOT com

I’m confused as to what the goals of FSAs are here. My understanding is
that they are supposed to be a very low-level high-performance type that’s
closely linked with the underlying memory representation. That’s why memory
order initialization and flattened indexing is allowed, isn’t it? Partial
indexing privileges one dimension over the others, precisely because one
dimension *should* be privileged over the others, because it is much faster
than a column slice. The partial indexing syntax is good because it
emphasizes that this is an inherently *fast* operation. Whereas arbitrary
row extraction should be a special function to emphasize that it is an
inherently *slow* operation.

···

On Sun, Jul 23, 2017 at 11:05 PM, Daryle Walker <darylew@mac.com> wrote:

On Jul 23, 2017, at 12:04 PM, Taylor Swift <kelvin13ma@gmail.com> wrote:

On Sun, Jul 23, 2017 at 3:08 AM, Daryle Walker <darylew@mac.com> wrote:

9. I don’t see the value in having both nested FSAs and multi-dimensional
FSAs. Aren’t they the same thing? For example, in the code snippet

Why does any language with multi-dimensional arrays (like Fortran or Ada)
have them? By this standard, no language should have multi-dimensional
arrays. They exist because of data modeling. Co-equal coordinates in the
model should be co-equal in their representation in the program. Yes, they
are implemented the same way underneath. We don’t copy C everywhere, so why
not take this opportunity to do better. Also, just using nesting could
imply that the intermediate array types have a meaning, but they might not
if they’re just implementation quirks and not part of the abstract model.

Nested arrays are not my solution for multi-coordinate indexing; use
multi-dimensional arrays for that. I mention nested arrays because:

   - Nested arrays fundamentally cannot be banned. (What if an element
   type is hidden behind a type-alias and is conditionally an array type?)

Doesn’t Swift have to resolve the types at some point anyway? If it’s

impossible to ban, we can allow it, but still make it unidiomatic. Nested
arrays are much messier to write than multidimensional arrays.

The new draft I’m writing downplays nested arrays a lot. They’re mentioned
in the section discussing the core element type (nee the inner non-array
type).

   - I need the definition to explain the “inner non-array type”
      - I need the inner non-array type to explain which pairings of
      FSAs for reshaping are legal. (And a similar reason for tuple conversion.)
      Note the two types can have different nesting levels.
   - I need to explain that empty arrays cannot be an array element
   type. (Should this be changed? What happens with tuples or structures
   containing empty tuples/structures as members? What about empty
   tuples/sturctures in “Array”? Banning empty arrays means we don’t have to
   worry about every array element being at the same address. The other way to
   solve this is to make them one byte (or word) long.)

let a = [;1, 2, 3, 4]
assert(a[0] == 1)
assert(a[1] == 2)
assert(a[2] == 3)
assert(a[3] == 4)
let b = a as [2, 2; Int]
assert(b[0, 0] == 1)
assert(b[0, 1] == 2)
assert(b[1, 0] == 3)
assert(b[1, 1] == 4)
let c = a as [2; [2; Int]]
assert(c[0][0] == 1)
assert(c[0][1] == 2)
assert(c[1][0] == 3)
assert(c[1][1] == 4)

There’s three syntaxes which accomplish two unique things. I lean towards
disallowing FSA nesting and instead allowing *incomplete* index lists to
partially unnest multidimensional FSAs. Let’s reserve “...” for
flexible array chained dereferencing.

I don’t understand what your incomplete index list idea is. And as I
said, the chaining technique is less I desire it and more I can’t ban it
and keep Swift features orthogonal.

Incomplete indexing means

let fsa:[5, 2; Int] = [5, 2; 2, 4, 3, 5, 4, 6, 5, 7, 6, 8]
fsa[3] // [2; 5, 7]

this would be the same as writing

let fsa:[5; [2; Int]] = [5; [2; 2, 4], [2; 3, 5], [2; 4, 6], [2; 5, 7], [2;
6, 8]]
fsa[3] // [2; 5, 7]

in your current system. This would obviate the need to nest FSAs for the
purpose of extracting entire rows of data.

Allowing partial indexing as you show it privileges one dimension over the
others, although they’re supposed to be co-equal and the reason a
particular dimension is privileged is due to an implementation detail. Or
would you allow incomplete indexing on other dimensions besides the first?
Where the true-multi-dimensional <-> nested FSA equivalence wouldn’t help
you (because the elements are dispersed in the whole array). With complete
generics, this could be a library function:

func removeRow<Dimension: Int, M…: Int, N…: Int, P: Int, T>(array: […M, P,
…N; T], row: Int) -> […M, …N; T] where #lengthof(M) == Dimension

let fsa:[2 * Int] = [2 * 5, 3] // [10, 3] ???

Correct. If you wanted a multidimensional array, that'd be written "let
nestedFSA: [2*[5*Int]]". Or, speculating a bit, I suppose maybe "let
nestedFSA: [[5*Int]*2]", if we wanted there to be a column-major option.
IMHO all those read better than this proposal's syntax.

No, what I’m saying is does the phrase “[2 * 5, 3]” mean a fixed size
array of length two and with the elements 5 and 3, or a flexible sized
array with two elements 10 and 3? This is v confusing and difficult to
read, especially when you have actual multiplications going on such as

let fsa:[2 * Int] = [2 * 3 * 5, 3] // [15, 3] ???

That's... huh? To me, "[2 * 3 * 5, 3]" should obviously evaluate to "[30,
3]". How are you getting that "[2*5*3, 3]" could be a 2-element FSA
containing 15 and 3? Are you suggesting that instead of "[value * value *
value, value]", it could be parsed as "[modifier value * value, value]"
(with `modifier` being "2 *")? To me, that syntax would *strongly*
suggest that the modifier only applies to the first element of the array,
which would mean the only other option for parsing it would be equivalent
to "[[3, 5], 3]", which is neither a match for fsa's type, nor a
semantically valid array (the elements have to be the same type), nor a
syntactically valid array (the nested array in the first element is missing
its "").

Well, that *is* the syntax you’re proposing right? What comes on the left
of the asterisk is the FSA dimensions, and what comes to the right is the
FSA elements. So `2` is the FSA length, and `3 * 5` and `3` are the two
elements in the FSA. Unless of course, the right-most asterisk is defined
to be the separator, in which case our FSA has *six* elements, the first
two of which are `5` and `3` (what if there was a `default:` argument?).
This seems v confusing to me, since we now have asterisk-as-separator and
asterisk-as-multiplication mixed together within the same brackets.

Using the *multiplication operator* as a *separator* character seems like

an extraordinarily bad idea.

Well, much to the dismay of my occasionally-inner Unicode fanboy, we
decided that we didn't want to make everyone have to figure out how to type
"×" to use a stdlib type (to the further dismay of my O-IUF, this is
actually a really good argument, especially since a likely use for FSA is
in embedded or systems programming, where you might need to use an editor
that doesn't support Unicode).

The text encoding of the source code shouldn’t have any effect on the
compiled target? And while the ◊ or × suggestions are semi-rhetorical,
given a choice between difficult-to-read syntax and unicode, I’ll choose
unicode every time. Swift is nowhere near the first language to use
unconventional symbols. Inserting special characters these days is barely
harder than typing a capital letter. They should be used sparingly but not
ruled out completely, and it doesn’t seem like there are many alternatives.

I would choose the unicode route for my projects as well, but locking
stdlib types or functionality behind unicode has been a no-go ever since
Swift was open-sourced (and presumably before then as well, since nothing
in the stdlib uses them). We couldn't even get the unicode operators for
set notation: "∩", "∪", "⊂", "⊃", "⊆", "⊇", "∈", "∋", and "∖" (maybe not
"∖"... it's been a while), accepted as *alternate* spellings for:
"setA.intersection(setB)", "setA.union(setB)", etc, back in the "Set
Algebra" proposal. I really doubt a proposal for FSAs with syntax involving
unicode will be accepted. Feel free to try, though. Maybe there's been a
change of heart since the topic last came up.

Unicode operators for set notation was a bad idea because there was a
clear, readable non-unicode alternative available — the plain spelled-out
methods. Here we are far more restricted in our options, so we may as well
consider Unicode as a possible alternative.

···

On Sun, Jul 23, 2017 at 5:48 PM, David Sweeris <davesweeris@mac.com> wrote:

On Jul 23, 2017, at 12:18, Taylor Swift <kelvin13ma@gmail.com> wrote:
On Sun, Jul 23, 2017 at 2:21 PM, David Sweeris <davesweeris@mac.com> > wrote:

On Jul 23, 2017, at 09:08, Taylor Swift <kelvin13ma@gmail.com> wrote:

Allowing partial indexing as you show it privileges one dimension over the others, although they’re supposed to be co-equal and the reason a particular dimension is privileged is due to an implementation detail.

Isn’t this a pretty important implementation detail? One of the reasons for introducing FSAs is for performance; physical memory layout is a key part of performance. Indexing the first k dimensions will return a contiguous block of memory, which is fast to read (in my simple mental model of memory, you’d only need a start position and a buffer length, although it’s probably more complicated than this in reality) and also cache-friendlier than accessing arbitrary indices due to the contiguity of the memory. This is an important optimization and programmers should be able to take advantage of it.

I wouldn’t oppose arbitrary partial indexing, but would suggest that to specify the indices along arbitrary dimensions require a method to indicate the performance cost of reading (and writing?) non-contiguous memory.

···

On Jul 23, 2017, at 11:22 PM, Daryle Walker via swift-evolution <swift-evolution@swift.org> wrote:

Allowing partial indexing as you show it privileges one dimension over the others, although they’re supposed to be co-equal and the reason a particular dimension is privileged is due to an implementation detail.

No, the type of the FSA's elements is what comes to the right: "[count * Type]". I don't recall any discussion around the value side of things, so I'd guess they would've just used the existing array literal syntax, "let fsa: [2*[2*Int]] = [[0, 1], [2, 3]]".

- Dave Sweeris

···

On Jul 23, 2017, at 8:32 PM, Taylor Swift <kelvin13ma@gmail.com> wrote:

On Sun, Jul 23, 2017 at 5:48 PM, David Sweeris <davesweeris@mac.com> wrote:

On Jul 23, 2017, at 12:18, Taylor Swift <kelvin13ma@gmail.com> wrote:

On Sun, Jul 23, 2017 at 2:21 PM, David Sweeris <davesweeris@mac.com> wrote:

On Jul 23, 2017, at 09:08, Taylor Swift <kelvin13ma@gmail.com> wrote:

let fsa:[2 * Int] = [2 * 5, 3] // [10, 3] ???

Correct. If you wanted a multidimensional array, that'd be written "let nestedFSA: [2*[5*Int]]". Or, speculating a bit, I suppose maybe "let nestedFSA: [[5*Int]*2]", if we wanted there to be a column-major option. IMHO all those read better than this proposal's syntax.

No, what I’m saying is does the phrase “[2 * 5, 3]” mean a fixed size array of length two and with the elements 5 and 3, or a flexible sized array with two elements 10 and 3? This is v confusing and difficult to read, especially when you have actual multiplications going on such as

let fsa:[2 * Int] = [2 * 3 * 5, 3] // [15, 3] ???

That's... huh? To me, "[2 * 3 * 5, 3]" should obviously evaluate to "[30, 3]". How are you getting that "[2*5*3, 3]" could be a 2-element FSA containing 15 and 3? Are you suggesting that instead of "[value * value * value, value]", it could be parsed as "[modifier value * value, value]" (with `modifier` being "2 *")? To me, that syntax would strongly suggest that the modifier only applies to the first element of the array, which would mean the only other option for parsing it would be equivalent to "[[3, 5], 3]", which is neither a match for fsa's type, nor a semantically valid array (the elements have to be the same type), nor a syntactically valid array (the nested array in the first element is missing its "").

Well, that is the syntax you’re proposing right? What comes on the left of the asterisk is the FSA dimensions, and what comes to the right is the FSA elements.

Between comma, semicolon, and colon, I think semicolon is the best choice
(though I would prefer double colon over all three). However I don’t think
we should discard possible alternatives just because they aren’t already
reserved separators. Neither ',', ';', ':', nor '::' is particularly
readable, and compiler parser code only needs to be written once, while
language syntax, once it’s decided on, is stuck with us forever.

···

On Sun, Jul 23, 2017 at 11:05 PM, Daryle Walker <darylew@mac.com> wrote:

> On Jul 23, 2017, at 3:18 PM, Taylor Swift via swift-evolution < > swift-evolution@swift.org> wrote:
>
>
> If we’re actually going to try and establish a relationship between the
FSA asterisk and the multiplication asterisk, this is even more
problematic. How does the asterisk work in FSA literals, where there is no
type annotation to go on the right of the asterisk?
>
> Also introducing contextual keywords like “of” is going to cause a huge
amount of problems with syntax highlighters considering how often the word
“of” is used as an argument label in Swift. The words “as” and “stride”
already make for some interesting code highlighting, “of” would take it to
a whole new level.

I think I mentioned it at the end of the proposal, but there’s a reason
I’m using comma/colon/semicolon for FSAs. They are already reserved
separators within Swift’s syntax. The multiplier ideas or “of” seem to be
just for cuteness; why take a token out from being free to reserved for a
purpose that can be mechanically done by an existing separator token.


Daryle Walker
Mac, Internet, and Video Game Junkie
darylew AT mac DOT com

This proposal gives FSAs their own literal syntax. You write [; 3, 5] to
make a FSA, not [3, 5].

···

On Sun, Jul 23, 2017 at 11:54 PM, David Sweeris <davesweeris@mac.com> wrote:

On Jul 23, 2017, at 8:32 PM, Taylor Swift <kelvin13ma@gmail.com> wrote:

On Sun, Jul 23, 2017 at 5:48 PM, David Sweeris <davesweeris@mac.com> > wrote:

On Jul 23, 2017, at 12:18, Taylor Swift <kelvin13ma@gmail.com> wrote:

On Sun, Jul 23, 2017 at 2:21 PM, David Sweeris <davesweeris@mac.com> >> wrote:

On Jul 23, 2017, at 09:08, Taylor Swift <kelvin13ma@gmail.com> wrote:

let fsa:[2 * Int] = [2 * 5, 3] // [10, 3] ???

Correct. If you wanted a multidimensional array, that'd be written "let
nestedFSA: [2*[5*Int]]". Or, speculating a bit, I suppose maybe "let
nestedFSA: [[5*Int]*2]", if we wanted there to be a column-major option.
IMHO all those read better than this proposal's syntax.

No, what I’m saying is does the phrase “[2 * 5, 3]” mean a fixed size
array of length two and with the elements 5 and 3, or a flexible sized
array with two elements 10 and 3? This is v confusing and difficult to
read, especially when you have actual multiplications going on such as

let fsa:[2 * Int] = [2 * 3 * 5, 3] // [15, 3] ???

That's... huh? To me, "[2 * 3 * 5, 3]" should obviously evaluate to
"[30, 3]". How are you getting that "[2*5*3, 3]" could be a 2-element FSA
containing 15 and 3? Are you suggesting that instead of "[value * value *
value, value]", it could be parsed as "[modifier value * value, value]"
(with `modifier` being "2 *")? To me, that syntax would *strongly*
suggest that the modifier only applies to the first element of the array,
which would mean the only other option for parsing it would be equivalent
to "[[3, 5], 3]", which is neither a match for fsa's type, nor a
semantically valid array (the elements have to be the same type), nor a
syntactically valid array (the nested array in the first element is missing
its "").

Well, that *is* the syntax you’re proposing right? What comes on the left
of the asterisk is the FSA dimensions, and what comes to the right is the
FSA elements.

No, the *type* of the FSA's elements is what comes to the right: "[count
* *Type*]". I don't recall any discussion around the value side of
things, so I'd guess they would've just used the existing array literal
syntax, "let fsa: [2*[2*Int]] = [[0, 1], [2, 3]]".

- Dave Sweeris

My vision of FSAs is as a low-ish mid-level type, not a low-level type and definitely not a very-low-level type. Yes, use as implementing parts of an abstract data type is a goal, otherwise why not stick with Array. And performance is a goal. But FSAs should be usable outside of that. That’s one reason my FSAs support multiple dimensions; it’s the opposite of K&R’s decision throwing out multiple dimensions in the original C when its contemporaries had them.

[Another reason for default support for multiple dimensions is that I don’t know if any processor vector-unit types model 2D arrays, or if all are 1D vectors. Limiting FSAs to one dimension means there’s no easy way to model 2D vector-type arrays. Using FSAs to bring processor vector-unit types to the user level is a core goal.]

Memory-order initialization for multi-dimensional arrays when not using explicit indexes is to save on needing to type out said indexes. And to help inform what elements are which when using static indexing. (Static indexing is flattened because my first attempt at making a multi-coordinate version of tuple’s anonymous member access looked dumb.)

By flattened indexing, do you mean the "withUnsafe*Flattening” functions? Those give the users a way to access the array as a collection. And it’s a way to handle functions that want an array of a particular element type, but for any length/shape, an adaptation of the “T” parameter type in C functions. The “T” parameter type let C programmers write a function for any array segment length, without specializations for “T[1],” “T[2],” “T[3],” and so on. (You have to pass the actual length separately.) This was before C++ templates and allowing function specializations per array length, but using the “T” saves on how many specializations are needed (just one instead of per array length used).

If you mean the “for-in” loop, the flattening is meant to be an abstraction. The C-style for loop was removed because we now abstract the iteration over collections so you don’t have to manually maintain an iteration counter. The flat for-loop removes having to manually write loop statements per dimension. If you don’t need the iterator-counter/iteration-coordinate, skipping the need to write the counter(s) anyway is a big savings. The new problem is what to do when you do want the iteration counter(s). For collections, use the “enumerated” method, which just returns a new sequence that is a pair of the original element and the would-have-been iteration counter. For FSAs, since iteration order is unspecified and copying to a bigger array is impractical, I use a new primary expression to get the counter.

To have partial indexing, and keep it only to the first (i.e. outermost) dimension, we can add a new set of global functions:

func withUnsafePartialIndexing<T, Result, M: Int, N…: Int>(of arg: inout [M, …N; T], _ body: (UnsafeBufferPointer<[…N; T]>) throws -> Result) rethrows -> Result

both mutable and immutable. Or maybe add a variant to target a specific row:

func withExtraction<T, Result, M: Int, N…: Int>(ofRow row: Int, from arg: inout [M, …N; T], body: ([…N; T]) throws -> Result) rethrows -> Result

(where the mutable version takes an “inout […N; T]” in the closure). If you want to strip more than one dimension, then do the subsequent dimensions within the closures. These functions would have to wait for complete generics, though.

In fact, the lack of a “constexpr” (to use a C++ term) story really limits FSA declarations (Right now, bounds must be integer literals.), let alone on how much complete generics would help.

···

On Jul 23, 2017, at 11:20 PM, Taylor Swift <kelvin13ma@gmail.com> wrote:

On Sun, Jul 23, 2017 at 11:05 PM, Daryle Walker <darylew@mac.com <mailto:darylew@mac.com>> wrote:

On Jul 23, 2017, at 12:04 PM, Taylor Swift <kelvin13ma@gmail.com <mailto:kelvin13ma@gmail.com>> wrote:

Incomplete indexing means

let fsa:[5, 2; Int] = [5, 2; 2, 4, 3, 5, 4, 6, 5, 7, 6, 8]
fsa[3] // [2; 5, 7]

this would be the same as writing

let fsa:[5; [2; Int]] = [5; [2; 2, 4], [2; 3, 5], [2; 4, 6], [2; 5, 7], [2; 6, 8]]
fsa[3] // [2; 5, 7]

in your current system. This would obviate the need to nest FSAs for the purpose of extracting entire rows of data.

Allowing partial indexing as you show it privileges one dimension over the others, although they’re supposed to be co-equal and the reason a particular dimension is privileged is due to an implementation detail. Or would you allow incomplete indexing on other dimensions besides the first? Where the true-multi-dimensional <-> nested FSA equivalence wouldn’t help you (because the elements are dispersed in the whole array). With complete generics, this could be a library function:

func removeRow<Dimension: Int, M…: Int, N…: Int, P: Int, T>(array: […M, P, …N; T], row: Int) -> […M, …N; T] where #lengthof(M) == Dimension

I’m confused as to what the goals of FSAs are here. My understanding is that they are supposed to be a very low-level high-performance type that’s closely linked with the underlying memory representation. That’s why memory order initialization and flattened indexing is allowed, isn’t it? Partial indexing privileges one dimension over the others, precisely because one dimension should be privileged over the others, because it is much faster than a column slice. The partial indexing syntax is good because it emphasizes that this is an inherently fast operation. Whereas arbitrary row extraction should be a special function to emphasize that it is an inherently slow operation.


Daryle Walker
Mac, Internet, and Video Game Junkie
darylew AT mac DOT com

Do FSAs really need special sugar, though? They won’t be an extremely heavily-used construct, but rather they’ll be occasionally used either for performance reasons or to interact with C APIs. Sure, C had a short syntax for making them, but making pointers in C was short, too, and that hasn’t been carried over into Swift. In fact, a FSA has a lot in common with an UnsafeBufferPointer that you don’t have to worry about deallocating. Furthermore, there are collection types such as Set and ContiguousArray which are arguably more useful than FSA, yet don’t have their own syntax.

Is this really not good enough?

let arr = FixedArray<Type>(capacity: x)

Charles

···

On Jul 23, 2017, at 11:03 PM, Taylor Swift via swift-evolution <swift-evolution@swift.org> wrote:

This proposal gives FSAs their own literal syntax. You write [; 3, 5] to make a FSA, not [3, 5].

On Sun, Jul 23, 2017 at 11:54 PM, David Sweeris <davesweeris@mac.com <mailto:davesweeris@mac.com>> wrote:

On Jul 23, 2017, at 8:32 PM, Taylor Swift <kelvin13ma@gmail.com <mailto:kelvin13ma@gmail.com>> wrote:

On Sun, Jul 23, 2017 at 5:48 PM, David Sweeris <davesweeris@mac.com <mailto:davesweeris@mac.com>> wrote:

On Jul 23, 2017, at 12:18, Taylor Swift <kelvin13ma@gmail.com <mailto:kelvin13ma@gmail.com>> wrote:

On Sun, Jul 23, 2017 at 2:21 PM, David Sweeris <davesweeris@mac.com <mailto:davesweeris@mac.com>> wrote:

On Jul 23, 2017, at 09:08, Taylor Swift <kelvin13ma@gmail.com <mailto:kelvin13ma@gmail.com>> wrote:

let fsa:[2 * Int] = [2 * 5, 3] // [10, 3] ???

Correct. If you wanted a multidimensional array, that'd be written "let nestedFSA: [2*[5*Int]]". Or, speculating a bit, I suppose maybe "let nestedFSA: [[5*Int]*2]", if we wanted there to be a column-major option. IMHO all those read better than this proposal's syntax.

No, what I’m saying is does the phrase “[2 * 5, 3]” mean a fixed size array of length two and with the elements 5 and 3, or a flexible sized array with two elements 10 and 3? This is v confusing and difficult to read, especially when you have actual multiplications going on such as

let fsa:[2 * Int] = [2 * 3 * 5, 3] // [15, 3] ???

That's... huh? To me, "[2 * 3 * 5, 3]" should obviously evaluate to "[30, 3]". How are you getting that "[2*5*3, 3]" could be a 2-element FSA containing 15 and 3? Are you suggesting that instead of "[value * value * value, value]", it could be parsed as "[modifier value * value, value]" (with `modifier` being "2 *")? To me, that syntax would strongly suggest that the modifier only applies to the first element of the array, which would mean the only other option for parsing it would be equivalent to "[[3, 5], 3]", which is neither a match for fsa's type, nor a semantically valid array (the elements have to be the same type), nor a syntactically valid array (the nested array in the first element is missing its "").

Well, that is the syntax you’re proposing right? What comes on the left of the asterisk is the FSA dimensions, and what comes to the right is the FSA elements.

No, the type of the FSA's elements is what comes to the right: "[count * Type]". I don't recall any discussion around the value side of things, so I'd guess they would've just used the existing array literal syntax, "let fsa: [2*[2*Int]] = [[0, 1], [2, 3]]".

- Dave Sweeris

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

It is not good enough for C interop because a design where the element count is data rather than part of the type cannot be layout-compatible with a C fixed-size array.

Félix

···

Le 23 juil. 2017 à 22:22, Charles Srstka via swift-evolution <swift-evolution@swift.org> a écrit :

Do FSAs really need special sugar, though? They won’t be an extremely heavily-used construct, but rather they’ll be occasionally used either for performance reasons or to interact with C APIs. Sure, C had a short syntax for making them, but making pointers in C was short, too, and that hasn’t been carried over into Swift. In fact, a FSA has a lot in common with an UnsafeBufferPointer that you don’t have to worry about deallocating. Furthermore, there are collection types such as Set and ContiguousArray which are arguably more useful than FSA, yet don’t have their own syntax.

Is this really not good enough?

let arr = FixedArray<Type>(capacity: x)

Charles

On Jul 23, 2017, at 11:03 PM, Taylor Swift via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

This proposal gives FSAs their own literal syntax. You write [; 3, 5] to make a FSA, not [3, 5].

On Sun, Jul 23, 2017 at 11:54 PM, David Sweeris <davesweeris@mac.com <mailto:davesweeris@mac.com>> wrote:

On Jul 23, 2017, at 8:32 PM, Taylor Swift <kelvin13ma@gmail.com <mailto:kelvin13ma@gmail.com>> wrote:

On Sun, Jul 23, 2017 at 5:48 PM, David Sweeris <davesweeris@mac.com <mailto:davesweeris@mac.com>> wrote:

On Jul 23, 2017, at 12:18, Taylor Swift <kelvin13ma@gmail.com <mailto:kelvin13ma@gmail.com>> wrote:

On Sun, Jul 23, 2017 at 2:21 PM, David Sweeris <davesweeris@mac.com <mailto:davesweeris@mac.com>> wrote:

On Jul 23, 2017, at 09:08, Taylor Swift <kelvin13ma@gmail.com <mailto:kelvin13ma@gmail.com>> wrote:

let fsa:[2 * Int] = [2 * 5, 3] // [10, 3] ???

Correct. If you wanted a multidimensional array, that'd be written "let nestedFSA: [2*[5*Int]]". Or, speculating a bit, I suppose maybe "let nestedFSA: [[5*Int]*2]", if we wanted there to be a column-major option. IMHO all those read better than this proposal's syntax.

No, what I’m saying is does the phrase “[2 * 5, 3]” mean a fixed size array of length two and with the elements 5 and 3, or a flexible sized array with two elements 10 and 3? This is v confusing and difficult to read, especially when you have actual multiplications going on such as

let fsa:[2 * Int] = [2 * 3 * 5, 3] // [15, 3] ???

That's... huh? To me, "[2 * 3 * 5, 3]" should obviously evaluate to "[30, 3]". How are you getting that "[2*5*3, 3]" could be a 2-element FSA containing 15 and 3? Are you suggesting that instead of "[value * value * value, value]", it could be parsed as "[modifier value * value, value]" (with `modifier` being "2 *")? To me, that syntax would strongly suggest that the modifier only applies to the first element of the array, which would mean the only other option for parsing it would be equivalent to "[[3, 5], 3]", which is neither a match for fsa's type, nor a semantically valid array (the elements have to be the same type), nor a syntactically valid array (the nested array in the first element is missing its "").

Well, that is the syntax you’re proposing right? What comes on the left of the asterisk is the FSA dimensions, and what comes to the right is the FSA elements.

No, the type of the FSA's elements is what comes to the right: "[count * Type]". I don't recall any discussion around the value side of things, so I'd guess they would've just used the existing array literal syntax, "let fsa: [2*[2*Int]] = [[0, 1], [2, 3]]".

- Dave Sweeris

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Yes, it’s not good enough. This looks like it would be a struct in the standard library. And named types have at least one initializer, and one of which must be called during non-assignment initializations. But named types must be completely initialized by the time any initializer ends, and that’s a non-goal for FSAs. My FSA design uses compound types so we can initialize in piecemeal. (We could suspend complete initialization for these static named array types, but that inconsistency would be a “cure worse than the disease” solution.)

Also, this looks like the array bounds are determined at run-time, requiring remote storage, which is an anti-goal. One of the main goals of FSAs is to use scoped storage (unlike Array) with easy indexing (unlike tuples). Newer versions of C have a function to dynamically use scoped storage, so we could use that, but we usually know what array shape we need at compile-time, so why move the decision to run-time? And dynamically determined scoped storage would screw up use as sub-objects.

If it’s not a named type, but a compound type with named-type-looking syntax, it’s too much of an anti-sugar solution.

···

On Jul 24, 2017, at 1:22 AM, Charles Srstka via swift-evolution <swift-evolution@swift.org> wrote:

Do FSAs really need special sugar, though? They won’t be an extremely heavily-used construct, but rather they’ll be occasionally used either for performance reasons or to interact with C APIs. Sure, C had a short syntax for making them, but making pointers in C was short, too, and that hasn’t been carried over into Swift. In fact, a FSA has a lot in common with an UnsafeBufferPointer that you don’t have to worry about deallocating. Furthermore, there are collection types such as Set and ContiguousArray which are arguably more useful than FSA, yet don’t have their own syntax.

Is this really not good enough?

let arr = FixedArray<Type>(capacity: x)


Daryle Walker
Mac, Internet, and Video Game Junkie
darylew AT mac DOT com

Which brings us I think full circle back to using literal values as generic parameters, "let fsa = FSA<Type, Count>(whateverArgs) //where `Count` is an integer literal, or some other integer value that can be determined at compile time".

- Dave Sweeris

···

On Jul 24, 2017, at 1:05 AM, Félix Cloutier via swift-evolution <swift-evolution@swift.org> wrote:

It is not good enough for C interop because a design where the element count is data rather than part of the type cannot be layout-compatible with a C fixed-size array.

Félix

Le 23 juil. 2017 à 22:22, Charles Srstka via swift-evolution <swift-evolution@swift.org> a écrit :

Do FSAs really need special sugar, though? They won’t be an extremely heavily-used construct, but rather they’ll be occasionally used either for performance reasons or to interact with C APIs. Sure, C had a short syntax for making them, but making pointers in C was short, too, and that hasn’t been carried over into Swift. In fact, a FSA has a lot in common with an UnsafeBufferPointer that you don’t have to worry about deallocating. Furthermore, there are collection types such as Set and ContiguousArray which are arguably more useful than FSA, yet don’t have their own syntax.

Is this really not good enough?

let arr = FixedArray<Type>(capacity: x)

Charles

On Jul 23, 2017, at 11:03 PM, Taylor Swift via swift-evolution <swift-evolution@swift.org> wrote:

This proposal gives FSAs their own literal syntax. You write [; 3, 5] to make a FSA, not [3, 5].

On Sun, Jul 23, 2017 at 11:54 PM, David Sweeris <davesweeris@mac.com> wrote:

On Jul 23, 2017, at 8:32 PM, Taylor Swift <kelvin13ma@gmail.com> wrote:

On Sun, Jul 23, 2017 at 5:48 PM, David Sweeris <davesweeris@mac.com> wrote:

On Jul 23, 2017, at 12:18, Taylor Swift <kelvin13ma@gmail.com> wrote:

On Sun, Jul 23, 2017 at 2:21 PM, David Sweeris <davesweeris@mac.com> wrote:

On Jul 23, 2017, at 09:08, Taylor Swift <kelvin13ma@gmail.com> wrote:

let fsa:[2 * Int] = [2 * 5, 3] // [10, 3] ???

Correct. If you wanted a multidimensional array, that'd be written "let nestedFSA: [2*[5*Int]]". Or, speculating a bit, I suppose maybe "let nestedFSA: [[5*Int]*2]", if we wanted there to be a column-major option. IMHO all those read better than this proposal's syntax.

No, what I’m saying is does the phrase “[2 * 5, 3]” mean a fixed size array of length two and with the elements 5 and 3, or a flexible sized array with two elements 10 and 3? This is v confusing and difficult to read, especially when you have actual multiplications going on such as

let fsa:[2 * Int] = [2 * 3 * 5, 3] // [15, 3] ???

That's... huh? To me, "[2 * 3 * 5, 3]" should obviously evaluate to "[30, 3]". How are you getting that "[2*5*3, 3]" could be a 2-element FSA containing 15 and 3? Are you suggesting that instead of "[value * value * value, value]", it could be parsed as "[modifier value * value, value]" (with `modifier` being "2 *")? To me, that syntax would strongly suggest that the modifier only applies to the first element of the array, which would mean the only other option for parsing it would be equivalent to "[[3, 5], 3]", which is neither a match for fsa's type, nor a semantically valid array (the elements have to be the same type), nor a syntactically valid array (the nested array in the first element is missing its "").

Well, that is the syntax you’re proposing right? What comes on the left of the asterisk is the FSA dimensions, and what comes to the right is the FSA elements.

No, the type of the FSA's elements is what comes to the right: "[count * Type]". I don't recall any discussion around the value side of things, so I'd guess they would've just used the existing array literal syntax, "let fsa: [2*[2*Int]] = [[0, 1], [2, 3]]".

- Dave Sweeris

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

There are other alternatives that don't use generics. Last time this came around, the straw man syntax was (4 x Int), and it was merely to be a shorthand for (Int, Int, Int, Int).

Every non-existing feature that needs to be implemented to make fixed-size arrays work are a drag. I've said it before and I'll say it again: major features that this proposal wants to rely on should be brought independently and discussed on their own. There are real problems with monolithic proposals:

They couple independent features in an all-or-nothing basket
They consume a huge amount of review and design energy
They force sub-features to be viewed through the telescope aimed at the main feature, and make it easier to miss problems or opportunities in the big pictures

The last point is especially worrying to me because things like non-type generic parameters are *much bigger* than fixed-size arrays. I think that it's a priority inversion to discuss non-type generic parameters as a bullet point of fixed-size arrays.

Félix

···

Le 24 juil. 2017 à 01:37, David Sweeris <davesweeris@mac.com> a écrit :

Which brings us I think full circle back to using literal values as generic parameters, "let fsa = FSA<Type, Count>(whateverArgs) //where `Count` is an integer literal, or some other integer value that can be determined at compile time".

- Dave Sweeris

On Jul 24, 2017, at 1:05 AM, Félix Cloutier via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

It is not good enough for C interop because a design where the element count is data rather than part of the type cannot be layout-compatible with a C fixed-size array.

Félix

Le 23 juil. 2017 à 22:22, Charles Srstka via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> a écrit :

Do FSAs really need special sugar, though? They won’t be an extremely heavily-used construct, but rather they’ll be occasionally used either for performance reasons or to interact with C APIs. Sure, C had a short syntax for making them, but making pointers in C was short, too, and that hasn’t been carried over into Swift. In fact, a FSA has a lot in common with an UnsafeBufferPointer that you don’t have to worry about deallocating. Furthermore, there are collection types such as Set and ContiguousArray which are arguably more useful than FSA, yet don’t have their own syntax.

Is this really not good enough?

let arr = FixedArray<Type>(capacity: x)

Charles

On Jul 23, 2017, at 11:03 PM, Taylor Swift via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

This proposal gives FSAs their own literal syntax. You write [; 3, 5] to make a FSA, not [3, 5].

On Sun, Jul 23, 2017 at 11:54 PM, David Sweeris <davesweeris@mac.com <mailto:davesweeris@mac.com>> wrote:

On Jul 23, 2017, at 8:32 PM, Taylor Swift <kelvin13ma@gmail.com <mailto:kelvin13ma@gmail.com>> wrote:

On Sun, Jul 23, 2017 at 5:48 PM, David Sweeris <davesweeris@mac.com <mailto:davesweeris@mac.com>> wrote:

On Jul 23, 2017, at 12:18, Taylor Swift <kelvin13ma@gmail.com <mailto:kelvin13ma@gmail.com>> wrote:

On Sun, Jul 23, 2017 at 2:21 PM, David Sweeris <davesweeris@mac.com <mailto:davesweeris@mac.com>> wrote:

On Jul 23, 2017, at 09:08, Taylor Swift <kelvin13ma@gmail.com <mailto:kelvin13ma@gmail.com>> wrote:

let fsa:[2 * Int] = [2 * 5, 3] // [10, 3] ???

Correct. If you wanted a multidimensional array, that'd be written "let nestedFSA: [2*[5*Int]]". Or, speculating a bit, I suppose maybe "let nestedFSA: [[5*Int]*2]", if we wanted there to be a column-major option. IMHO all those read better than this proposal's syntax.

No, what I’m saying is does the phrase “[2 * 5, 3]” mean a fixed size array of length two and with the elements 5 and 3, or a flexible sized array with two elements 10 and 3? This is v confusing and difficult to read, especially when you have actual multiplications going on such as

let fsa:[2 * Int] = [2 * 3 * 5, 3] // [15, 3] ???

That's... huh? To me, "[2 * 3 * 5, 3]" should obviously evaluate to "[30, 3]". How are you getting that "[2*5*3, 3]" could be a 2-element FSA containing 15 and 3? Are you suggesting that instead of "[value * value * value, value]", it could be parsed as "[modifier value * value, value]" (with `modifier` being "2 *")? To me, that syntax would strongly suggest that the modifier only applies to the first element of the array, which would mean the only other option for parsing it would be equivalent to "[[3, 5], 3]", which is neither a match for fsa's type, nor a semantically valid array (the elements have to be the same type), nor a syntactically valid array (the nested array in the first element is missing its "").

Well, that is the syntax you’re proposing right? What comes on the left of the asterisk is the FSA dimensions, and what comes to the right is the FSA elements.

No, the type of the FSA's elements is what comes to the right: "[count * Type]". I don't recall any discussion around the value side of things, so I'd guess they would've just used the existing array literal syntax, "let fsa: [2*[2*Int]] = [[0, 1], [2, 3]]".

- Dave Sweeris

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

+ all the 1s

- Dave Sweeris

···

On Jul 24, 2017, at 9:22 AM, Félix Cloutier <felixcca@yahoo.ca> wrote:

There are other alternatives that don't use generics. Last time this came around, the straw man syntax was (4 x Int), and it was merely to be a shorthand for (Int, Int, Int, Int).

Every non-existing feature that needs to be implemented to make fixed-size arrays work are a drag. I've said it before and I'll say it again: major features that this proposal wants to rely on should be brought independently and discussed on their own. There are real problems with monolithic proposals:

They couple independent features in an all-or-nothing basket
They consume a huge amount of review and design energy
They force sub-features to be viewed through the telescope aimed at the main feature, and make it easier to miss problems or opportunities in the big pictures

The last point is especially worrying to me because things like non-type generic parameters are *much bigger* than fixed-size arrays. I think that it's a priority inversion to discuss non-type generic parameters as a bullet point of fixed-size arrays.

The last point is especially worrying to me because things like non-type generic parameters are *much bigger* than fixed-size arrays.

Why do you think that's the case?

And even if it's really more challenging than FSAs:
Would that be enough justification to add a bunch of language changes right now, ignoring more general concepts which offer a good syntax for them without extra cost?

The last point is especially worrying to me because things like non-type generic parameters are *much bigger* than fixed-size arrays.

Why do you think that's the case?

This is a bit of a naive thing to say since we don't have non-type generic parameters, but it seems to me that there's essentially no contention that if we had it, we'd only need a shorthand (N x T) syntax to create a tuple of N objects of type T to implement a FixedSizeArray<T, N> struct in the standard library. It would already respond to the biggest needs: it can be layout-compatible with arrays in C structs, the tuple syntax migration is manageable (if we even want it), implementing Sequence on it is easy, it has well-understood copy semantics, the type declaration is unambiguous.

By contrast, the "non-type generic parameters" point hides that, at the very least, the ABI needs to change to support this and the generic syntax will need a makeover to support both type and non-type parameters. In addition, they will almost certainly motivate a debate on what "constant expression" means in Swift and the possibilities of compile-time evaluation. They open up other type possibilities that will probably need to be discussed, like `Foo<N>: Foo<N-1>`. And of course, that doesn't even mention that Swift still hasn't realized its "baseline vision" <https://github.com/apple/swift/blob/master/docs/GenericsManifesto.md&gt; of generics.

It's also a matter of impact. Fixed-size arrays are useful, to me included, but they don't really create new opportunities for things that just couldn't be done before. Non-type generic parameters do.

And even if it's really more challenging than FSAs:
Would that be enough justification to add a bunch of language changes right now, ignoring more general concepts which offer a good syntax for them without extra cost?

It seems to me that I'm the one advocating for fewer language changes, and the majority of sub-features that are being requested here don't feel particularly more general to me.

In its current form, this proposal tackles a contentious syntax to declare fixed-length arrays and a similarly contentious syntax to initialize them, it has multi-dimensional arrays, unpacking of arrays as parameter lists, zero-size types with alignment requirements, sized array literals, explicit conversions between array types, rules for deterministic initialization, vector types. Out of these, I could see parameter unpacking and vectors used for more than fixed-size arrays. (I haven't been through the entire discussion, though, so you might be able to point out a few more.)

There's also a number of issues that aren't addressed in the document, which I feel are obscured by the sheer number of things that it asks to consider: for instance, as we mentioned on another thread, Swift anonymous types can't conform to protocols, so it's not clear what fixed-size arrays have to be under the hood to be iterable.

Of course, if you take all of that, that's possibly bigger than non-type generic parameters, but I question whether it all needs to pass at the same time, or even if there are things that could be dropped to make this more manageable.

···

Le 24 juil. 2017 à 10:43, Tino Heth <2th@gmx.de> a écrit :

It seems to me that I'm the one advocating for fewer language changes, and the majority of sub-features that are being requested here don't feel particularly more general to me.

In its current form, this proposal tackles a contentious syntax to declare fixed-length arrays and a similarly contentious syntax to initialize them, it has multi-dimensional arrays, unpacking of arrays as parameter lists, zero-size types with alignment requirements, sized array literals, explicit conversions between array types, rules for deterministic initialization, vector types. Out of these, I could see parameter unpacking and vectors used for more than fixed-size arrays. (I haven't been through the entire discussion, though, so you might be able to point out a few more.)

On “unpacking of arrays as parameter lists,” are you talking about tuple conversion? That’s mainly to convert legacy C-conversions, which are manually homogenous tuples, to proper arrays. I added a little generalization instead of requiring a strict flat “(T, T, …, T, T)” format for the tuple type. If I didn’t need that legacy support, I probably wouldn’t have added tuple conversion at all.

So zero-size arrays should have no alignment requirements? Looking at a playground, empty tuples (both “()” and “((), ())”) have zero size but a stride of 1. Since elements of an array are spaced out by stride instead of size, what happens if an empty array is used as an element type. Zero-size arrays should take up at least a stride of 1, but if not rounded up to the element type’s alignment, then the array alignment won’t match the element alignment. These worries are why I initially banned empty arrays from being element types. Should I go back to that?

The proposal technically does not affect the rules for deterministic initialization. The only point of note is since FSAs are aggregate compound types, an instance's elements’ DI statuses are tracked separately, just like tuple members. Everything in the rest of that section, besides future suggestions, falls into place using the existing DI rules.

Since FSAs are a new kind of type, new ABI entries need to be formed. A reason to mention vector mode now is that using a processor vector-unit type or not affects the implementation of a FSA, hence its ABI. I want to put all the parameters on FSA that could affect the ABI in at once, so we don’t have to propose another ABI change later. This definitely includes vector mode, and may include multi-dimensionality.

There's also a number of issues that aren't addressed in the document, which I feel are obscured by the sheer number of things that it asks to consider: for instance, as we mentioned on another thread, Swift anonymous types can't conform to protocols, so it's not clear what fixed-size arrays have to be under the hood to be iterable.

Did you look over the document? There’s a whole section on element traversal.

If you really want a Collection, and/or you want a Swift version of the “T” parameter interface from C where the argument can be an array of any length but a constant type, then use “withUnsafe(Mutable)Flattening”. If you want to iterate without converting to a Collection first, then you can use a FSA as the target of a “for-in” loop directly. If you need the iteration counter during the for-loop, a spiritual equivalent to Collection’s “enumerated," then use the new “#indexOf” primary expression.

Iteration order of a FSA during a “for-in” loop is unspecified. That’s because I want to allow the compiler to pick what it thinks is the best order (which may not be storage order (but probably would be)). And I want to allow the compiler to use simultaneous (or other overlapping) orders. And that previous point is to allow processor vector-unit types as FSA implementations.

Of course, if you take all of that, that's possibly bigger than non-type generic parameters, but I question whether it all needs to pass at the same time, or even if there are things that could be dropped to make this more manageable.

I already have dropped some things. Not sure how much I can trim down and keep Version 1 of FSAs useable.

···

On Jul 25, 2017, at 2:14 AM, Félix Cloutier via swift-evolution <swift-evolution@swift.org> wrote:


Daryle Walker
Mac, Internet, and Video Game Junkie
darylew AT mac DOT com