[Pitch] New Version of Array Proposal

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.

No, I am talking about the `b[ [;1, 4] ]` syntax.

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.

I was merely enumerating the entirety of the features that your proposal requires to be implemented, as a response to Tino saying that I was suggesting more features that were less general.

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.

Yes, there is a section on array traversal, but there is a difference between saying "this needs to work" and "here's how it's going to work". If you're looking for what I missed, that would be that fixed-size arrays are meant to be their own special category of types, and not sugar on top of something else.

Speaking of things that are not addressed in the document, then, would be what any of this looks like at the SIL level. In fact, your proposal never spells out "SIL".

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”.

We can already essentially do that with tuples. In fact, that's the current workaround for C arrays.

Do you have code that currently tries to do C interop with fixed-size arrays? Have you identified pain points with that existing Swift code that you would like to make better with your fixed-size array proposal? Or is helping C interop only a secondary goal?

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.

It is my humble opinion that fixed-size arrays lose a lot of their usefulness if they can't at least be treated as Sequences.

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.

Why should fixed-size arrays have this special behavior over normal arrays? I find it hard to justify that fixed-size arrays iterate fundamentally differently from both variable-sized arrays in Swift and fixed-size arrays in C. I also don't see why the unspecified faster iteration algorithm could fundamentally only apply to fixed-size arrays. To me, that's a prime example of something that could be dropped.

Félix

···

Le 29 juil. 2017 à 16:01, Daryle Walker <darylew@mac.com> a écrit :

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

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.

No, I am talking about the `b[ [;1, 4] ]` syntax.

I didn’t have that at first. Later, I added “#indexOf”. That operator does not dump a bunch of comma-separated tokens; it returns a full object (a one-dimensional fixed-size integer array). To actually be usable in indexing a parallel array of the same shape, I needed to either explode the array to a comma-separated list of integers, or add a subscript operator that takes all the indexes as a single object. The second one seems easier, especially since “comma-separated tokens of some kind” isn’t a Swift entity (at least not yet).

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?

In the update I’m working on, empty arrays take no size when they’re sub-objects (in a structure, tuple, or fixed-size array), but a minimal size when they’re top-level objects (globals and function locals).

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.

I was merely enumerating the entirety of the features that your proposal requires to be implemented, as a response to Tino saying that I was suggesting more features that were less general.

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.

Yes, there is a section on array traversal, but there is a difference between saying "this needs to work" and "here's how it's going to work". If you're looking for what I missed, that would be that fixed-size arrays are meant to be their own special category of types, and not sugar on top of something else.

Speaking of things that are not addressed in the document, then, would be what any of this looks like at the SIL level. In fact, your proposal never spells out "SIL”.

Because I don’t know that much about it. I know a little more about LLVM and the ABI; so their contributions to implementation are mentioned in the proposal.

I’m not a compiler writer, so it’s less me implementing all the features at the compiler and support levels and more getting/giving mutual feedback with the people who do that work on what can/should be done.

So, I need to research this SIL and figure out if I need to add descriptions for this level.

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”.

We can already essentially do that with tuples. In fact, that's the current workaround for C arrays.

Tuples don’t have run-time indexing (for now, anyway), so don’t work as a solution for Collection.

Manually homogenous tuples are a workaround, so that use should be retired once something more on-point comes along. (I’m trying to design said “more on-point.”)

Do you have code that currently tries to do C interop with fixed-size arrays? Have you identified pain points with that existing Swift code that you would like to make better with your fixed-size array proposal? Or is helping C interop only a secondary goal?

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.

It is my humble opinion that fixed-size arrays lose a lot of their usefulness if they can't at least be treated as Sequences.

I do have thoughts on how FSAs could work with the common algorithms, but I think that Sequence & Collection may have been the wrong abstraction to put them. Some of the algorithms can work for anything container-like, not just sequenced collections. We need new protocols to separate concepts more and have Sequence/Collection conform to those.

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.

Why should fixed-size arrays have this special behavior over normal arrays? I find it hard to justify that fixed-size arrays iterate fundamentally differently from both variable-sized arrays in Swift and fixed-size arrays in C. I also don't see why the unspecified faster iteration algorithm could fundamentally only apply to fixed-size arrays. To me, that's a prime example of something that could be dropped.

FSAs intentionally don’t conform to Collection, because multi-dimensional arrays shouldn’t have to conform to a linear (by nature, hence the name “Sequence”) standard, at least by default. I didn’t want FSAs to be potentially held back by concessions to linearity. Why throw away optimizations that letting the compiler/system decide the visitation path could enable?

The existing containers can’t follow the road to arbitrary visitation orders because their very own base protocol, Sequence, is modeled not to do this. (They’re linear and forward, i.e. sequential.)

···

On Jul 30, 2017, at 4:54 PM, Félix Cloutier <felixcca@yahoo.ca> wrote:

Le 29 juil. 2017 à 16:01, Daryle Walker <darylew@mac.com> a écrit :

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

FSAs intentionally don’t conform to Collection, because multi-dimensional arrays shouldn’t have to conform to a linear (by nature, hence the name “Sequence”) standard, at least by default.

I strongly oppose and think it is a really bad idea:
Even if arrays are modelled multi-dimensional, there's always a canonical way to iterate through their elements, and this is an essential feature of this data type.

Do you have any example for an existing optimisation that is important enough to cripple all fixed size arrays?
Those would not only be used to represent pixel buffers on a graphics card…

Also, if FSA have only one dimension (that's still my preference), all those issues are can be solved easily in the multidimensional structure build on top of the array.

FSAs intentionally don’t conform to Collection, because multi-dimensional arrays shouldn’t have to conform to a linear (by nature, hence the name “Sequence”) standard, at least by default.

I strongly oppose and think it is a really bad idea:
Even if arrays are modelled multi-dimensional, there's always a canonical way to iterate through their elements, and this is an essential feature of this data type.

But linear access isn’t an inherent canonical property of multi-dimensional arrays, it’s just a consequence of arrays taking a contiguous block of memory (which is generally treated as linear in computers).

Speaking of which, the “withUnsafe(Mutable)Flattening” functions give Collection access. (And it serves as an equivalent to the “T” function parameter interface from C.)

I was going to support Collection for one-dimensional arrays, but I realized that would be a bad idea since that’s the dimensionality that would exploit vector-unit types the most. So you must convert first. (Well, the “conversion” to an Unsafe(Mutable)BufferPointer should just type-pun the address, unless the array was not initially in conventional addressable memory, which (small) objects aren’t by default in Swift, hence the “Unsafe” part of Swift’s pointer interface.)

Do you have any example for an existing optimisation that is important enough to cripple all fixed size arrays?
Those would not only be used to represent pixel buffers on a graphics card…

Sequence/Collection have other problems fitting with fixed-size arrays. There needs to be a new set of more basic protocols that both arrays and Sequence or Collection can conform to.

Also, if FSA have only one dimension (that's still my preference), all those issues are can be solved easily in the multidimensional structure build on top of the array.

Or to flip it, just use multi-dimensional arrays with one bound. Multi-dimensionality does not impose an implementation penalty, especially when declaring a one-dimensional array. Wrapping multi-dimensionality in a type would forfeit it being a compound type, which would forfeit piecemeal initialization. There’s no need for Swift arrays to be limited to C arrays plus Assignability (or be just C arrays plus Assignability plus Collection).

···

On Aug 1, 2017, at 3:21 AM, Tino Heth <2th@gmx.de> wrote:


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

But linear access isn’t an inherent canonical property of multi-dimensional arrays, it’s just a consequence of arrays taking a contiguous block of memory (which is generally treated as linear in computers).

Do you know about any attempts to change this? I've seen setups of two-dimensional memory — but only on bit level, and this was mapped into one dimension...
Todays computers rely heavily on memory being organised in linear fashion, and I don't think this will change in the near future.
But anyways, that wasn't the canonical order in an array I ways writing about:
Even if we had n-dimensional hardware, there would be little doubt that (0, 0, 0, 0, 0) is the first element, (0, 0, 0, 0, 1) the second, and that (0, 1, 0, 0, 0) comes after (0, 0, 1, 0, 0) (endianness left aside ;-)

Sequence/Collection have other problems fitting with fixed-size arrays. There needs to be a new set of more basic protocols that both arrays and Sequence or Collection can conform to.

What exactly is the problem with Sequence that makes you believe there is need for a more basic protocol?

Or to flip it, just use multi-dimensional arrays with one bound. Multi-dimensionality does not impose an implementation penalty

I'd call the (imho extremely) increased complexity and loosing conformance to Collection a heave penalty… actually, it would strip arrays of their biggest unique feature compared to tuples.
And after all, all arrays have to be mapped to a single dimension, so I don't see the ability to define an array with ten dimensions on the fly as a big win (because it's rather easy to derive such a type from a one-dimensional array).

Wrapping multi-dimensionality in a type would forfeit it being a compound type, which would forfeit piecemeal initialization.

[Basic question: What definition of compound type are you referring to?]
Why would there be a fundamental difference in initialisation between an array, and an object that holds an array and maps to its contents?
[ah, I think I got that point: It's not about leaving parts uninitialised and taking care of them later, but the ability to use literals like
[[[0, 0, 1], [0, 1, 0]], [0, 0, 2], [0, 2, 0]]]
right?]

- Tino

But linear access isn’t an inherent canonical property of multi-dimensional arrays, it’s just a consequence of arrays taking a contiguous block of memory (which is generally treated as linear in computers).

Do you know about any attempts to change this? I've seen setups of two-dimensional memory — but only on bit level, and this was mapped into one dimension...
Todays computers rely heavily on memory being organised in linear fashion, and I don't think this will change in the near future.
But anyways, that wasn't the canonical order in an array I ways writing about:
Even if we had n-dimensional hardware, there would be little doubt that (0, 0, 0, 0, 0) is the first element, (0, 0, 0, 0, 1) the second, and that (0, 1, 0, 0, 0) comes after (0, 0, 1, 0, 0) (endianness left aside ;-)

It is important to separate the concept of linearity of indices from linearity of physical memory addresses. I think the latter is what Daryle might be alluding to, where there are many physical layout techniques such as tiling which have dramatic performance impact depending on the access pattern. For example, these techniques are extremely important to graphics and image processing (see http://halide-lang.org and http://people.csail.mit.edu/jrk/jrkthesis.pdf\).

Obviously tuples of natural numbers can be mapped to the natural numbers, the real design decision here is how to expose multi-dimensional indices as a programming model.

···

On Aug 1, 2017, at 10:03 AM, Tino Heth via swift-evolution <swift-evolution@swift.org> wrote:

Sequence/Collection have other problems fitting with fixed-size arrays. There needs to be a new set of more basic protocols that both arrays and Sequence or Collection can conform to.

What exactly is the problem with Sequence that makes you believe there is need for a more basic protocol?

Or to flip it, just use multi-dimensional arrays with one bound. Multi-dimensionality does not impose an implementation penalty

I'd call the (imho extremely) increased complexity and loosing conformance to Collection a heave penalty… actually, it would strip arrays of their biggest unique feature compared to tuples.
And after all, all arrays have to be mapped to a single dimension, so I don't see the ability to define an array with ten dimensions on the fly as a big win (because it's rather easy to derive such a type from a one-dimensional array).

Wrapping multi-dimensionality in a type would forfeit it being a compound type, which would forfeit piecemeal initialization.

[Basic question: What definition of compound type are you referring to?]
Why would there be a fundamental difference in initialisation between an array, and an object that holds an array and maps to its contents?
[ah, I think I got that point: It's not about leaving parts uninitialised and taking care of them later, but the ability to use literals like
[[[0, 0, 1], [0, 1, 0]], [0, 0, 2], [0, 2, 0]]]
right?]

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

Sequence/Collection have other problems fitting with fixed-size arrays. There needs to be a new set of more basic protocols that both arrays and Sequence or Collection can conform to.

What exactly is the problem with Sequence that makes you believe there is need for a more basic protocol?

For one, the return value of map is wrong. Sequence.map returns an Array, since a Sequence may not be a container itself. Using Array may be a minor inconvenience for Collection. But it’s a huge surprise if a fixed-size array’s map doesn’t return another fixed-size array of the same shape (not necessarily the same element type).

Or to flip it, just use multi-dimensional arrays with one bound. Multi-dimensionality does not impose an implementation penalty

I'd call the (imho extremely) increased complexity and loosing conformance to Collection a heave penalty… actually, it would strip arrays of their biggest unique feature compared to tuples.
And after all, all arrays have to be mapped to a single dimension, so I don't see the ability to define an array with ten dimensions on the fly as a big win (because it's rather easy to derive such a type from a one-dimensional array).

I said that not even one-dimensional arrays can support Collection by default, so ripping out multi-dimensional support won’t bring Collection back for 1D arrays. (Before that I was going to support Collection for just 1D arrays, so keeping multi-dimensional support or not wouldn’t change.)

Anyway, withUnsafe(Mutable)Flattening would be available as a standard global function for your Collection needs. It just isn’t built into the array types.

Wrapping multi-dimensionality in a type would forfeit it being a compound type, which would forfeit piecemeal initialization.

[Basic question: What definition of compound type are you referring to?]

Compound types: functions and tuples. Versus named types: structures, classes, and enumerations.

Why would there be a fundamental difference in initialisation between an array, and an object that holds an array and maps to its contents?

A tuple can have its members initialized in piecemeal and still satisfy deterministic initialization. The named types need to do all their sub-objects' initializations before any designated initializer ends. I want the former for array instances, not the latter. It’s important for numeric applications, so math arrays don’t have to be set twice, once for an arbitrary default and again for the real data.

[ah, I think I got that point: It's not about leaving parts uninitialised and taking care of them later, but the ability to use literals like
[[[0, 0, 1], [0, 1, 0]], [0, 0, 2], [0, 2, 0]]]
right?]

It is about delaying initializations. But I don’t know what you mean about your statement about literals.

···

On Aug 1, 2017, at 1:03 PM, Tino Heth <2th@gmx.de> wrote:


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

Eh? What do you mean by "initialized in piecemeal"? These both give errors:
let x:(Int, Int) = (0) // something about not being able to convert `Int` to `(Int, Int)`
let x:(Int, Int) = (0, _) // something about "_" only being allowed in patterns

Is that what you're talking about?

- Dave Sweeris

···

On Aug 1, 2017, at 10:54 AM, Daryle Walker via swift-evolution <swift-evolution@swift.org> wrote:

A tuple can have its members initialized in piecemeal and still satisfy deterministic initialization. The named types need to do all their sub-objects' initializations before any designated initializer ends. I want the former for array instances, not the latter. It’s important for numeric applications, so math arrays don’t have to be set twice, once for an arbitrary default and again for the real data.

What exactly is the problem with Sequence that makes you believe there is need for a more basic protocol?

For one, the return value of map is wrong. Sequence.map returns an Array, since a Sequence may not be a container itself. Using Array may be a minor inconvenience for Collection. But it’s a huge surprise if a fixed-size array’s map doesn’t return another fixed-size array of the same shape (not necessarily the same element type).

So would you say Dictionary shouldn't conform to Collection either?
Just because a type conforms to a protocol doesn't mean it can't add its own methods on top.

Or to flip it, just use multi-dimensional arrays with one bound. Multi-dimensionality does not impose an implementation penalty

I'd call the (imho extremely) increased complexity and loosing conformance to Collection a heave penalty… actually, it would strip arrays of their biggest unique feature compared to tuples.
And after all, all arrays have to be mapped to a single dimension, so I don't see the ability to define an array with ten dimensions on the fly as a big win (because it's rather easy to derive such a type from a one-dimensional array).

I said that not even one-dimensional arrays can support Collection by default, so ripping out multi-dimensional support won’t bring Collection back for 1D arrays. (Before that I was going to support Collection for just 1D arrays, so keeping multi-dimensional support or not wouldn’t change.)

Swift has one-dimensional arrays, and they support Collection... this may sound like nitpicking that only works because there is no explicit "fixed-size" in you statement, but feel free to prove me wrong for FSAs.

Anyway, withUnsafe(Mutable)Flattening would be available as a standard global function for your Collection needs. It just isn’t built into the array types.

So people should get used to use an "unsafe" method for basic tasks like iteration?

Wrapping multi-dimensionality in a type would forfeit it being a compound type, which would forfeit piecemeal initialization.

[Basic question: What definition of compound type are you referring to?]

Compound types: functions and tuples. Versus named types: structures, classes, and enumerations.

[never seen functions classified as a compound type, but that doesn't matter here]

Why would there be a fundamental difference in initialisation between an array, and an object that holds an array and maps to its contents?

A tuple can have its members initialized in piecemeal and still satisfy deterministic initialization. The named types need to do all their sub-objects' initializations before any designated initializer ends. I want the former for array instances, not the latter. It’s important for numeric applications, so math arrays don’t have to be set twice, once for an arbitrary default and again for the real data.

let f: Array<Float, size: 3> = [0, 9.81, 0]
Where's f filled with arbitrary default?

[ah, I think I got that point: It's not about leaving parts uninitialised and taking care of them later, but the ability to use literals like
[[[0, 0, 1], [0, 1, 0]], [0, 0, 2], [0, 2, 0]]]
right?]

It is about delaying initializations. But I don’t know what you mean about your statement about literals.

Then I've no clue what you want to achieve; can you give an example in pseudocode?

- Tino

I think he means that you can do

var x: (Int,Int)
x.0 = 0
x.1 = 1

This is generally not allowed for other aggregates outside of initializers.

John.

···

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

On Aug 1, 2017, at 10:54 AM, Daryle Walker via swift-evolution <swift-evolution@swift.org> wrote:

A tuple can have its members initialized in piecemeal and still satisfy deterministic initialization. The named types need to do all their sub-objects' initializations before any designated initializer ends. I want the former for array instances, not the latter. It’s important for numeric applications, so math arrays don’t have to be set twice, once for an arbitrary default and again for the real data.

Eh? What do you mean by "initialized in piecemeal"? These both give errors:
let x:(Int, Int) = (0) // something about not being able to convert `Int` to `(Int, Int)`
let x:(Int, Int) = (0, _) // something about "_" only being allowed in patterns

Is that what you're talking about?

What exactly is the problem with Sequence that makes you believe there is need for a more basic protocol?

For one, the return value of map is wrong. Sequence.map returns an Array, since a Sequence may not be a container itself. Using Array may be a minor inconvenience for Collection. But it’s a huge surprise if a fixed-size array’s map doesn’t return another fixed-size array of the same shape (not necessarily the same element type).

So would you say Dictionary shouldn't conform to Collection either?
Just because a type conforms to a protocol doesn't mean it can't add its own methods on top.

But the FSA interface and the Sequence/Collection interface would be very similar, basically competing, leading to a schizophrenic interface. Since another part of the overall FSA interface implements Collection, just use that.

Or to flip it, just use multi-dimensional arrays with one bound. Multi-dimensionality does not impose an implementation penalty

I'd call the (imho extremely) increased complexity and loosing conformance to Collection a heave penalty… actually, it would strip arrays of their biggest unique feature compared to tuples.
And after all, all arrays have to be mapped to a single dimension, so I don't see the ability to define an array with ten dimensions on the fly as a big win (because it's rather easy to derive such a type from a one-dimensional array).

I said that not even one-dimensional arrays can support Collection by default, so ripping out multi-dimensional support won’t bring Collection back for 1D arrays. (Before that I was going to support Collection for just 1D arrays, so keeping multi-dimensional support or not wouldn’t change.)

Swift has one-dimensional arrays, and they support Collection... this may sound like nitpicking that only works because there is no explicit "fixed-size" in you statement, but feel free to prove me wrong for FSAs.

Yes, I meant FSAs, not both them and Array; it’s long-winded to keep adding the “fixed-size” part.

Anyway, withUnsafe(Mutable)Flattening would be available as a standard global function for your Collection needs. It just isn’t built into the array types.
So people should get used to use an "unsafe" method for basic tasks like iteration?

withUnsafeFlattening is not the main FSA iteration task; it’s still the for-loop. If you don’t care how traversal occurs, there’s no problem. Since FSAs are built-ins instead of library types, I want the compiler to have the freedom to determine its iteration method. If you care about a particular traversal path, then implement the looping manually; you shouldn’t be hoping that whatever order I’m convince to canonize happens to match your desired order (or use withUnsafeFlattening if you want storage order). If you manually loop not for the path order but to know the index, there’s the “#indexOf” expression as the equivalent to Sequence.enumerated().

But wait, wouldn’t storage order be the best order? Maybe, leaning towards yes, but there’s no reason to insist on it in case we’re wrong.

I’m not starting with Collection and trying to make FSAs fit, but starting from the other direction, and seeing how compatible the interfaces are.

Wrapping multi-dimensionality in a type would forfeit it being a compound type, which would forfeit piecemeal initialization.

[Basic question: What definition of compound type are you referring to?]

Compound types: functions and tuples. Versus named types: structures, classes, and enumerations.

[never seen functions classified as a compound type, but that doesn't matter here]

Why would there be a fundamental difference in initialisation between an array, and an object that holds an array and maps to its contents?

A tuple can have its members initialized in piecemeal and still satisfy deterministic initialization. The named types need to do all their sub-objects' initializations before any designated initializer ends. I want the former for array instances, not the latter. It’s important for numeric applications, so math arrays don’t have to be set twice, once for an arbitrary default and again for the real data.

let f: Array<Float, size: 3> = [0, 9.81, 0]
Where's f filled with arbitrary default?

Your example has the all elements initialized in the literal, so it doesn’t matter here. But if you had 4 elements listed in the “size” part and kept the literal at 3 initializing values:

(1) “Array” here is a named type (class/struct/enum), so you violated DI in your initializer
(2) “Array” is a compound type although it looks like a named type. That’s confusing. (DI is satisfied as long as the last element is initialized before it, or the object as a whole, is read.)
[(3) “Array” is a type-alias to a more punctuator-soup-looking compound type. That’s legal, but still a little confusing.]

[ah, I think I got that point: It's not about leaving parts uninitialised and taking care of them later, but the ability to use literals like
[[[0, 0, 1], [0, 1, 0]], [0, 0, 2], [0, 2, 0]]]
right?]

It is about delaying initializations. But I don’t know what you mean about your statement about literals.

Then I've no clue what you want to achieve; can you give an example in pseudocode?

My “delaying initializations” is the same as your “leaving parts uninitialized and taking care of them later.” I can’t give an example since you still haven’t explained what “but the ability to use literals…” means, so I can’t determine the contrast.

···

On Aug 1, 2017, at 2:55 PM, Tino Heth <2th@gmx.de> wrote:


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

I’m -1 on adding a fixed-sized Array type.

It goes back to something which I remember reading from John McCall earlier this week but can’t find any more: about tuple indices being nominal and not ordinal. How do fixed-size Arrays differ? Are their indexes truly not nominal?

The difference between a fixed-size array and the dynamically-sized Array we already have is that the programmer expects specific data at each element. Maybe it’s elements of a vector or matrix, or some other structure, but in general I think that constraints about the size/shape of the sequence implies expectations about what you’re going to find at each location. Maybe you would normally write a struct for it, but it’s not worth writing out. In that sense, how is it different from a homogenous tuple?

Also, what effect would this have on Array as the common-currency for simple lists? And what about the literals - does [myObj, anotherObj] give you a [MyObject] or a [2; MyObject]? Is that what users will intuitively expect? What about if it’s a “let” constant?

So overall, I’m unconvinced of the need for fixed-size arrays. My counter-proposal would be a shorthand syntax for more conveniently defining homogenous tuples, and keep them as our go-to objects for ad-hoc groups of things. That’s it. If you would have used a fixed-size Array in C, keep using homogenous tuples in Swift.

As for the part about the @vector and @parallel attributes, those would be worth a separate proposal. As for @parallel, I suggested something like that before but Dave Abrahams said any such support would look more like a generic concurrent wrapper, e.g. https://gist.github.com/karwa/43ae838809cc68d317003f2885c71572\. Vector support is worth thinking about in a separate proposal.

Yes, this.

···

On Aug 1, 2017, at 7:21 PM, John McCall <rjmccall@apple.com> wrote:

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

On Aug 1, 2017, at 10:54 AM, Daryle Walker via swift-evolution <swift-evolution@swift.org> wrote:

A tuple can have its members initialized in piecemeal and still satisfy deterministic initialization. The named types need to do all their sub-objects' initializations before any designated initializer ends. I want the former for array instances, not the latter. It’s important for numeric applications, so math arrays don’t have to be set twice, once for an arbitrary default and again for the real data.

Eh? What do you mean by "initialized in piecemeal"? These both give errors:
let x:(Int, Int) = (0) // something about not being able to convert `Int` to `(Int, Int)`
let x:(Int, Int) = (0, _) // something about "_" only being allowed in patterns

Is that what you're talking about?

I think he means that you can do

var x: (Int,Int)
x.0 = 0
x.1 = 1

This is generally not allowed for other aggregates outside of initializers.


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

Hi Daryle,

I think we agree a lot on the importance of fixed-size arrays, but have a different opinion on which aspect is the most valuable… (so we now only have to agree that mine is better ;-) ;-)
My motivation for FSA is safety and convenience:
I want to iterate over C arrays in a straightforward way, but primarily, I don't want to accidentally multiply a vector of size 3 with a 2×2 matrix.
Of course, fast is cool, but I don't expect to suffer from bad performance because of implementation details like how, where and when memory allocation happens.
Your focus, on the other hand, seems to be performance:
You don't want to give guarantees about the order because of (hypothetical?) optimisations that could be blocked by that, and avoid initialisation overhead.

You brought "withUnsafeFlattening" to the table to add convenience, but I think that is the wrong direction:
Safe should be default, and it's quite common that you have to live with "unsafe" when you need "fast".

As you don't want to confirm to Sequence at all, it shouldn't bother you if the iterator sacrifices a tiny bit of performance in exchange for a reliable order, and when you really need piecemeal initialisation, you could take a FSA-Variant that skips initialisation of elements.
Of course, that wouldn't be ideal, and there should be an "Unsafe" in the name of that type — but I don't think tuple-like delayed initialisation would help when solving real-world problems:
The "x.0 = 0; x.1 = 1" case is trivial and can be done with normal init, and when this isn't enough, you most likely loose all guarantees because you use a loop to fill that array*.

I really appreciate the effort you spend for digging into the low-level details, and hope that we end up with a draft that satisfies your use case.

- Tino

* There are actually cases where you want to compute the value of one element based on another one, but that might as well be an indicator that you are better off with a tuple, instead of using an array.

So would you say Dictionary shouldn't conform to Collection either?
Just because a type conforms to a protocol doesn't mean it can't add its own methods on top.

But the FSA interface and the Sequence/Collection interface would be very similar, basically competing, leading to a schizophrenic interface. Since another part of the overall FSA interface implements Collection, just use that.

Yes, I can't argue against the claim that Collection sometimes feels a little bit odd :-( — but it is what it is, and maybe there will be improvements in the future that could take into account the experience with FSA.

Swift has one-dimensional arrays, and they support Collection... this may sound like nitpicking that only works because there is no explicit "fixed-size" in you statement, but feel free to prove me wrong for FSAs.

Yes, I meant FSAs, not both them and Array; it’s long-winded to keep adding the “fixed-size” part.

So we do agree that there is no fundamental reason that stops FSAs from being collections? ;-)

Anyway, withUnsafe(Mutable)Flattening would be available as a standard global function for your Collection needs. It just isn’t built into the array types.
So people should get used to use an "unsafe" method for basic tasks like iteration?

withUnsafeFlattening is not the main FSA iteration task; it’s still the for-loop. If you don’t care how traversal occurs, there’s no problem. Since FSAs are built-ins instead of library types, I want the compiler to have the freedom to determine its iteration method. If you care about a particular traversal path, then implement the looping manually; you shouldn’t be hoping that whatever order I’m convince to canonize happens to match your desired order (or use withUnsafeFlattening if you want storage order). If you manually loop not for the path order but to know the index, there’s the “#indexOf” expression as the equivalent to Sequence.enumerated().

But wait, wouldn’t storage order be the best order? Maybe, leaning towards yes, but there’s no reason to insist on it in case we’re wrong.

I’m not starting with Collection and trying to make FSAs fit, but starting from the other direction, and seeing how compatible the interfaces are.

(1) “Array” here is a named type (class/struct/enum), so you violated DI in your initializer
(2) “Array” is a compound type although it looks like a named type. That’s confusing. (DI is satisfied as long as the last element is initialized before it, or the object as a whole, is read.)
[(3) “Array” is a type-alias to a more punctuator-soup-looking compound type. That’s legal, but still a little confusing.]

I think FSAs should as much as possible behave like todays Array, so (1) is my choice.

[ah, I think I got that point: It's not about leaving parts uninitialised and taking care of them later, but the ability to use literals like
[[[0, 0, 1], [0, 1, 0]], [0, 0, 2], [0, 2, 0]]]
right?]

It is about delaying initializations. But I don’t know what you mean about your statement about literals.

Then I've no clue what you want to achieve; can you give an example in pseudocode?

My “delaying initializations” is the same as your “leaving parts uninitialized and taking care of them later.” I can’t give an example since you still haven’t explained what “but the ability to use literals…” means, so I can’t determine the contrast.

I even gave a explicit example! ;-)
As you meant something else, it doesn't matter — but if multi-dimensionality would be integrated into the core of Swift, there would be the option of special syntax.

I’m -1 on adding a fixed-sized Array type.

It goes back to something which I remember reading from John McCall earlier this week but can’t find any more: about tuple indices being nominal and not ordinal. How do fixed-size Arrays differ? Are their indexes truly not nominal?

I think he meant that the numbered names for tuple members were originally (?) there because the Swift authors didn’t mandate each member needing a label, so there needed some way to refer to unnamed members. Note that numbered names are not true integer variables, not even useable as such. Array indexes are programmable objects; algorithms on the indexes is how we select array subsets to apply algorithms on.

The difference between a fixed-size array and the dynamically-sized Array we already have is that the programmer expects specific data at each element. Maybe it’s elements of a vector or matrix, or some other structure, but in general I think that constraints about the size/shape of the sequence implies expectations about what you’re going to find at each location. Maybe you would normally write a struct for it, but it’s not worth writing out. In that sense, how is it different from a homogenous tuple?

I’m not sure what you mean here. How do elements of dynamically-sized arrays not have expectations?

The big innovation arrays (and loops) brought was no longer having a per-sub-object declaration/command for elements. Just tweak a number.

I’m not good at explicit explanations, so having to justify adding a type that’s been around for a long time (at least FORTRAN 4+ decades ago) an almost every systems programming language has is frustrating. I thought the desire would be obvious; if there were FSAs in Swift 1, would there be any “just slap Collection on tuples and be done with it” suggestions now? It doesn’t help that I still don’t know why FSAs where skipped in Swift 1; did they forget or was there some high-level type-theory reason? (Were the type description records in the Swift ABI too fragile for a type that wouldn’t have per-sub-object entries (assuming theoretical Swift-1-FSAs weren’t translated to massive homogenous tuples)?)

I mentioned in my proposal that no language (that I know of) splatted tuple and array syntax together, either declaration syntax or dereferencing syntax. (Lua has shared dereferencing syntax, but they both rip-off dictionaries.) Where do people think every one else over the last few decades went wrong?

Maybe there’s a copy of the FORTRAN design documents out there?...

Also, what effect would this have on Array as the common-currency for simple lists? And what about the literals - does [myObj, anotherObj] give you a [MyObject] or a [2; MyObject]? Is that what users will intuitively expect? What about if it’s a “let” constant?

Later revisions of the proposal have a distinct grid literal syntax, to clear up any potential confusion. The standard array literals would map to Array. The grid literal, which includes the dimensions of the array before a list of each value, would map to a fixed-size array.

So overall, I’m unconvinced of the need for fixed-size arrays. My counter-proposal would be a shorthand syntax for more conveniently defining homogenous tuples, and keep them as our go-to objects for ad-hoc groups of things. That’s it. If you would have used a fixed-size Array in C, keep using homogenous tuples in Swift.

As for the part about the @vector and @parallel attributes, those would be worth a separate proposal. As for @parallel, I suggested something like that before but Dave Abrahams said any such support would look more like a generic concurrent wrapper, e.g. https://gist.github.com/karwa/43ae838809cc68d317003f2885c71572\. Vector support is worth thinking about in a separate proposal.

A main point for my FSA design is that I want to allow the default iteration primitive (for-loop) to have a vectorized/parallel implementation (someday). Since Sequence/Collection always has a sequential traversal policy (It’s in the name!), it’s the main reason FSA don’t directly conform to Collection in the design.

···

On Aug 2, 2017, at 4:44 PM, Karl Wagner via swift-evolution <swift-evolution@swift.org> wrote:


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

FSA indices may be nominal, but you still need some way to store them. A
good example of this is when you’re implementing cubemaps with 3-tuple
vectors. Selecting a cube face involves selecting components of the vector
at a variable offset supplied by a function parameter. Doing this with a switch
case is hideously verbose and introduces a lot of unnecessary branching.

···

On Wed, Aug 2, 2017 at 4:44 PM, Karl Wagner via swift-evolution < swift-evolution@swift.org> wrote:

I’m -1 on adding a fixed-sized Array type.

It goes back to something which I remember reading from John McCall
earlier this week but can’t find any more: about tuple indices being
nominal and not ordinal. How do fixed-size Arrays differ? Are their indexes
truly not nominal?

The difference between a fixed-size array and the dynamically-sized Array
we already have is that the programmer expects specific data at each
element. Maybe it’s elements of a vector or matrix, or some other
structure, but in general I think that constraints about the size/shape of
the sequence implies expectations about what you’re going to find at each
location. Maybe you would normally write a struct for it, but it’s not
worth writing out. In that sense, how is it different from a homogenous
tuple?

Also, what effect would this have on Array as the common-currency for
simple lists? And what about the literals - does [myObj, anotherObj] give
you a [MyObject] or a [2; MyObject]? Is that what users will intuitively
expect? What about if it’s a “let” constant?

So overall, I’m unconvinced of the need for fixed-size arrays. My
counter-proposal would be a shorthand syntax for more conveniently defining
homogenous tuples, and keep them as our go-to objects for ad-hoc groups of
things. That’s it. If you would have used a fixed-size Array in C, keep
using homogenous tuples in Swift.

As for the part about the @vector and @parallel attributes, those would be
worth a separate proposal. As for @parallel, I suggested something like
that before but Dave Abrahams said any such support would look more like a
generic concurrent wrapper, e.g. karwa’s gists · GitHub
43ae838809cc68d317003f2885c71572. Vector support is worth thinking about
in a separate proposal.

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

Hi Daryle,

I think we agree a lot on the importance of fixed-size arrays, but have a different opinion on which aspect is the most valuable… (so we now only have to agree that mine is better ;-) ;-)
My motivation for FSA is safety and convenience:
I want to iterate over C arrays in a straightforward way, but primarily, I don't want to accidentally multiply a vector of size 3 with a 2×2 matrix.

Data modeling is important for me too. That’s why the proposal includes multi-dimensionality and why I didn’t just jam in Collection support. We don’t want to add conformance then find out that was a mistake.

Of course, fast is cool, but I don't expect to suffer from bad performance because of implementation details like how, where and when memory allocation happens.
Your focus, on the other hand, seems to be performance:
You don't want to give guarantees about the order because of (hypothetical?) optimisations that could be blocked by that, and avoid initialisation overhead.

I also don’t want to block parallel/vector processing.

let a: @vector [4; Int] = //…
let b: @vector [4; Int] = //…
var c: @vector [4; Int] = //…
//…
loop: for i in a {
    c[ #indexOf(loop) ] = i * b[ #indexOf(loop) ]
}
//…

I want the compiler to potentially be able to see that the elements are being computed in formation and use vector-unit instructions instead of serial processing.

You brought "withUnsafeFlattening" to the table to add convenience, but I think that is the wrong direction:
Safe should be default, and it's quite common that you have to live with "unsafe" when you need "fast".

The name has “Unsafe” because the Collection type used, UnsafeBufferPointer, does. I don’t know enough about what makes the existing “Unsafe” API that way for the flattening function to declared “safe”. It could be safe for all I know.

A substitute Collection-access function besides “withUnsafeFlattening” would either copy the elements (i.e. be inefficient, especially for large arrays) or somehow secretly maintain a reference to the array in memory. The latter would then be “withUnsafeFlattening” with a prettier name.

My first reason for “withUnsafeFlattening” was to allow API to use any FSA of a given element type, no matter the shape.

As you don't want to confirm to Sequence at all, it shouldn't bother you if the iterator sacrifices a tiny bit of performance in exchange for a reliable order, and when you really need piecemeal initialisation, you could take a FSA-Variant that skips initialisation of elements.
Of course, that wouldn't be ideal, and there should be an "Unsafe" in the name of that type — but I don't think tuple-like delayed initialisation would help when solving real-world problems:
The "x.0 = 0; x.1 = 1" case is trivial and can be done with normal init, and when this isn't enough, you most likely loose all guarantees because you use a loop to fill that array*.

Using a loop for array initialization is why I suggested we should look into run-time DI, which should be kept to restricted circumstances.

I really appreciate the effort you spend for digging into the low-level details, and hope that we end up with a draft that satisfies your use case.

- Tino

* There are actually cases where you want to compute the value of one element based on another one, but that might as well be an indicator that you are better off with a tuple, instead of using an array.

So would you say Dictionary shouldn't conform to Collection either?
Just because a type conforms to a protocol doesn't mean it can't add its own methods on top.

But the FSA interface and the Sequence/Collection interface would be very similar, basically competing, leading to a schizophrenic interface. Since another part of the overall FSA interface implements Collection, just use that.

Yes, I can't argue against the claim that Collection sometimes feels a little bit odd :-( — but it is what it is, and maybe there will be improvements in the future that could take into account the experience with FSA.

Swift has one-dimensional arrays, and they support Collection... this may sound like nitpicking that only works because there is no explicit "fixed-size" in you statement, but feel free to prove me wrong for FSAs.

Yes, I meant FSAs, not both them and Array; it’s long-winded to keep adding the “fixed-size” part.

So we do agree that there is no fundamental reason that stops FSAs from being collections? ;-)

Besides that they can’t be Sequences, unless you throw away allowing parallel/vector processing in the future. (That can’t be bolted onto Version 2, since committing to Sequence means you committed to single-thread iteration.) Just found out that C++ 17 (optionally) adds parallel/vector processing to its for-loops. I guess I caught on to a trend.

···

On Aug 3, 2017, at 7:20 AM, Tino Heth <2th@gmx.de> wrote:


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

This is purely a guess, but I think it was just that there's only so much time and there's not much that actually *requires* FSAs, other than to remove overhead.

Actually, as they've been described in this thread, I think that's all they do? The way we'd previously discussed them, they could conform to protocols and such, like any other type.

- Dave Sweeris

···

On Aug 2, 2017, at 21:45, Daryle Walker via swift-evolution <swift-evolution@swift.org> wrote:

I’m not good at explicit explanations, so having to justify adding a type that’s been around for a long time (at least FORTRAN 4+ decades ago) an almost every systems programming language has is frustrating. I thought the desire would be obvious; if there were FSAs in Swift 1, would there be any “just slap Collection on tuples and be done with it” suggestions now? It doesn’t help that I still don’t know why FSAs where skipped in Swift 1; did they forget or was there some high-level type-theory reason? (Were the type description records in the Swift ABI too fragile for a type that wouldn’t have per-sub-object entries (assuming theoretical Swift-1-FSAs weren’t translated to massive homogenous tuples)?)

I’m -1 on adding a fixed-sized Array type.

It goes back to something which I remember reading from John McCall earlier this week but can’t find any more: about tuple indices being nominal and not ordinal. How do fixed-size Arrays differ? Are their indexes truly not nominal?

I think he meant that the numbered names for tuple members were originally (?) there because the Swift authors didn’t mandate each member needing a label, so there needed some way to refer to unnamed members. Note that numbered names are not true integer variables, not even useable as such. Array indexes are programmable objects; algorithms on the indexes is how we select array subsets to apply algorithms on.

Yes, essentially. I was making this argument on a slightly higher level, just thinking about the meaning of values separate from any syntax.

A fixed-sized array is still fundamentally an array: it's a sequence of homogenous elements, where relative positions generally have some level of meaning. In an array like [A,B,C,D], it's probably *significant* that A comes first and that C comes before D. On some level, if it wasn't true that the order was significant, it wouldn't "really" be an array, it would be a set (or multiset) being represented using an array.

In contrast, a tuple is more like a jumble of independent values, ordered only because in this benighted world we can't really write them down at the same time. If you know someone's name and age, and you have to scribble them both down on a piece of paper, it doesn't really change anything which one you write first. At most there's some arbitrary convention for the order, like putting x before y in Cartesian coordinates.

We can choose different types for different purposes because they convey different things about the values they store. Isomorphism is not meaning.

The difference between a fixed-size array and the dynamically-sized Array we already have is that the programmer expects specific data at each element. Maybe it’s elements of a vector or matrix, or some other structure, but in general I think that constraints about the size/shape of the sequence implies expectations about what you’re going to find at each location. Maybe you would normally write a struct for it, but it’s not worth writing out. In that sense, how is it different from a homogenous tuple?

I’m not sure what you mean here. How do elements of dynamically-sized arrays not have expectations?

The big innovation arrays (and loops) brought was no longer having a per-sub-object declaration/command for elements. Just tweak a number.

I’m not good at explicit explanations, so having to justify adding a type that’s been around for a long time (at least FORTRAN 4+ decades ago) an almost every systems programming language has is frustrating. I thought the desire would be obvious; if there were FSAs in Swift 1, would there be any “just slap Collection on tuples and be done with it” suggestions now? It doesn’t help that I still don’t know why FSAs where skipped in Swift 1; did they forget or was there some high-level type-theory reason? (Were the type description records in the Swift ABI too fragile for a type that wouldn’t have per-sub-object entries (assuming theoretical Swift-1-FSAs weren’t translated to massive homogenous tuples)?)

They just weren't a priority. There are many things I wish we had done more work on before we released Swift 1, but trying to perfectly represent everything in C type system is not one of them.

Reasons not to prioritize fixed-sized arrays:
1. Variably-sized arrays are a much more important data structure. Fixed sized arrays are easier to make perform well, but they are inflexible and only narrowly useful.
2. The bound introduces significant expressional complexity to the type system. What types are eligible as bounds? What sorts of inference and meta-programming are possible on bounds? etc.
3. The language/library interactions are complex. It's a general data structure that demands proper integration with the rest of the collections library, but the language also really needs to hard-code an exact representation. So it would take a lot of work to integrate.

Honestly, a lot of this still applies. I would like to see fixed-sized arrays in the language eventually, but they are not going to become a priority, because there's a lot of other stuff that is more important to work on.

John.

···

On Aug 3, 2017, at 12:45 AM, Daryle Walker <darylew@mac.com> wrote:

On Aug 2, 2017, at 4:44 PM, Karl Wagner via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

I mentioned in my proposal that no language (that I know of) splatted tuple and array syntax together, either declaration syntax or dereferencing syntax. (Lua has shared dereferencing syntax, but they both rip-off dictionaries.) Where do people think every one else over the last few decades went wrong?

Maybe there’s a copy of the FORTRAN design documents out there?...

Also, what effect would this have on Array as the common-currency for simple lists? And what about the literals - does [myObj, anotherObj] give you a [MyObject] or a [2; MyObject]? Is that what users will intuitively expect? What about if it’s a “let” constant?

Later revisions of the proposal have a distinct grid literal syntax, to clear up any potential confusion. The standard array literals would map to Array. The grid literal, which includes the dimensions of the array before a list of each value, would map to a fixed-size array.

So overall, I’m unconvinced of the need for fixed-size arrays. My counter-proposal would be a shorthand syntax for more conveniently defining homogenous tuples, and keep them as our go-to objects for ad-hoc groups of things. That’s it. If you would have used a fixed-size Array in C, keep using homogenous tuples in Swift.

As for the part about the @vector and @parallel attributes, those would be worth a separate proposal. As for @parallel, I suggested something like that before but Dave Abrahams said any such support would look more like a generic concurrent wrapper, e.g. https://gist.github.com/karwa/43ae838809cc68d317003f2885c71572\. Vector support is worth thinking about in a separate proposal.

A main point for my FSA design is that I want to allow the default iteration primitive (for-loop) to have a vectorized/parallel implementation (someday). Since Sequence/Collection always has a sequential traversal policy (It’s in the name!), it’s the main reason FSA don’t directly conform to Collection in the design.


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

We don’t want to add conformance then find out that was a mistake.

I think we also don't want to create restrictions based on future additions that might never happen...

Besides that they can’t be Sequences, unless you throw away allowing parallel/vector processing in the future. (That can’t be bolted onto Version 2, since committing to Sequence means you committed to single-thread iteration.)

… especially as I doubt that those restrictions are required at all:
As I said, just conforming to collection doesn't forbid to add things that aren't in the protocol.
Why should it be impossible to add vector processing support when it is decided that this feature should be added to the language?

Parallel processing would be nice for Array<T> as well — and I can't think of someone really arguing to remove conformance to Sequence from Array now…

The situation is very different with Array<T, size: Int>:
If it is decided to add generic value parameters* to Swift, it imho would be awkward not to utilise this powerful for fixed-size arrays, and all those syntax-additions that are discussed for them would become very questionable at least.

Tino
Which imho definitely should happen: Whereas many additions to Swift are more a less a question of personal preference, generic value parameters offer protection from some kinds of bugs whose severity can actually be proven with real-word examples that had terrible consequences.