Proposal: Contiguous Variables (A.K.A. Fixed Sized Array Type)

That looks great except that I would prefer (4 * Int). Having "x" as an
operator looks very odd to me, and it doesn't fit with the rest of the
language.

···

On Thu, Jan 28, 2016 at 8:07 PM, Erica Sadun via swift-evolution < swift-evolution@swift.org> wrote:

I find

let values: (4 x Int) = (1, 2, 3, 4)

to be adequately cromulent. I believe this approach to be:

* Readable, even to someone unfamiliar with the syntax
* The parens before the assignment suggest something to do with tuples,
and the numbers match the arity after the assignment
* The type is preserved in-place
* It's compact, elegant, simple

-- E

On Jan 28, 2016, at 5:56 PM, Joe Groff via swift-evolution < > swift-evolution@swift.org> wrote:

On Jan 28, 2016, at 4:04 PM, Haravikk <e-mail@haravikk.me> wrote:

On 28 Jan 2016, at 22:37, Joe Groff via swift-evolution < > swift-evolution@swift.org> wrote:

On Jan 28, 2016, at 2:36 PM, Jacob Bandes-Storch <jtbandes@gmail.com> > wrote:

I like this idea, but the syntax seems dangerously close to a call site
for "func *(lhs: Int, rhs: Any.Type)" (which is obviously ill-advised,
but it is allowed).

Maybe we could take advantage of something which would be very invalid
under the current grammar, namely (n T) rather than (n * T):

   let values: (4 Int) = (1, 2, 3, 4)

Sure, or we could lift (4 x Int) from LLVM IR's syntax.

How about:

let values:Int[4] = (1,2,3,4)

While it looks a bit like a subscript, it doesn’t make sense in a type
declaration at present, so could be a good way to define restrictions of
this type (we could even extend it to collections later). If the similarity
is too close then:

let values:(Int[4]) = (1,2,3,4)

Could work too? Just some alternatives anyway, as I like the idea.

This kind of syntax doesn't compose well with other type productions. If
you parse Int[N][M] naively as (Int[N])[M], then you end up with an array
of M (array of N (Int)), which ends up subscripting in the opposite order,
array[0..<M][0..<N]. C works around this by flipping the order of multiple
array indices in a type declaration, so int [n][m] is really (int [m]) [n],
but this doesn't work well for Swift, which has other postfix type
productions—how would Int[N]?[M] parse? Choosing a prefix notation for
fixed-sized array bounds is better IMO to avoid these pitfalls.

-Joe

_______________________________________________
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

--
Trent Nadeau

I will make an attempt at a first draft given what I’ve read in this thread. I’m a little fuzzy on how to proceed as the process document makes mention of using the template and getting refinements on the mailing list before making a PR with the proposal. I have been having trouble finding examples of that in prior threads. Should I post the initial markdown to the thread?

···

On Jan 28, 2016, at 9:57 PM, Chris Lattner <clattner@apple.com> wrote:

On Jan 28, 2016, at 5:07 PM, Erica Sadun via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

I find

let values: (4 x Int) = (1, 2, 3, 4)

to be adequately cromulent. I believe this approach to be:

* Readable, even to someone unfamiliar with the syntax
* The parens before the assignment suggest something to do with tuples, and the numbers match the arity after the assignment
* The type is preserved in-place
* It's compact, elegant, simple

+1. I like this syntax too, and with Joe’s other proposed extensions, it would all fit together nicely. Anyone interested in writing up a proposal?

-Chris

-- E

On Jan 28, 2016, at 5:56 PM, Joe Groff via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Jan 28, 2016, at 4:04 PM, Haravikk <e-mail@haravikk.me <mailto:e-mail@haravikk.me>> wrote:

On 28 Jan 2016, at 22:37, Joe Groff via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Jan 28, 2016, at 2:36 PM, Jacob Bandes-Storch <jtbandes@gmail.com <mailto:jtbandes@gmail.com>> wrote:

I like this idea, but the syntax seems dangerously close to a call site for "func *(lhs: Int, rhs: Any.Type)" (which is obviously ill-advised, but it is allowed).

Maybe we could take advantage of something which would be very invalid under the current grammar, namely (n T) rather than (n * T):

   let values: (4 Int) = (1, 2, 3, 4)

Sure, or we could lift (4 x Int) from LLVM IR's syntax.

How about:

  let values:Int[4] = (1,2,3,4)

While it looks a bit like a subscript, it doesn’t make sense in a type declaration at present, so could be a good way to define restrictions of this type (we could even extend it to collections later). If the similarity is too close then:

  let values:(Int[4]) = (1,2,3,4)

Could work too? Just some alternatives anyway, as I like the idea.

This kind of syntax doesn't compose well with other type productions. If you parse Int[N][M] naively as (Int[N])[M], then you end up with an array of M (array of N (Int)), which ends up subscripting in the opposite order, array[0..<M][0..<N]. C works around this by flipping the order of multiple array indices in a type declaration, so int [n][m] is really (int [m]) [n], but this doesn't work well for Swift, which has other postfix type productions—how would Int[N]?[M] parse? Choosing a prefix notation for fixed-sized array bounds is better IMO to avoid these pitfalls.

-Joe

_______________________________________________
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

Currently, arrays contained in C structures are exported as tuples to Swift. If tuples need magic to align like C arrays, that magic already exists. Operators can't appear inside a type, so I don't think that it would be a problem to reuse * there either.

Aesthetically speaking, I think that (N x Type) looks better than (N * Type), but I don't like that (0xBeef) is either a tuple of 0 Beef objects or a hex number, which would be a problem if Swift must allow integers a type parameters.

Félix

···

Le 28 janv. 2016 à 22:12:29, Justin Kolb via swift-evolution <swift-evolution@swift.org> a écrit :

I’m not sure I like the fact that they would be associated with tuples. As far as I’m aware tuples don’t have a public or well documented memory layout and most likely it would be better to keep them that way. To be compatible with C a fixed size array would have to have similar memory layout requirements. Also I assume there was a reason not to allow subscripting of tuples originally and adding it to something similar might confuse things. If any of these things are non-issues then I’m fine with them looking like tuples. I do think they will need to be able to be initialized with array like initializers in some form.

I somewhat wish they would have been added in originally as it seems like it will be trickier to find a good form that isn’t already taken. I think it would probably be problematic for the parser to make use of `*` or `x`. Maybe after moving the count to the front of the declaration `:` would end up being different enough from other uses of `:` to make this work:

let values: (4:Int)

On Jan 28, 2016, at 9:04 PM, Trent Nadeau <tanadeau@gmail.com <mailto:tanadeau@gmail.com>> wrote:

That looks great except that I would prefer (4 * Int). Having "x" as an operator looks very odd to me, and it doesn't fit with the rest of the language.

On Thu, Jan 28, 2016 at 8:07 PM, Erica Sadun via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
I find

let values: (4 x Int) = (1, 2, 3, 4)

to be adequately cromulent. I believe this approach to be:

* Readable, even to someone unfamiliar with the syntax
* The parens before the assignment suggest something to do with tuples, and the numbers match the arity after the assignment
* The type is preserved in-place
* It's compact, elegant, simple

-- E

On Jan 28, 2016, at 5:56 PM, Joe Groff via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Jan 28, 2016, at 4:04 PM, Haravikk <e-mail@haravikk.me <mailto:e-mail@haravikk.me>> wrote:

On 28 Jan 2016, at 22:37, Joe Groff via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Jan 28, 2016, at 2:36 PM, Jacob Bandes-Storch <jtbandes@gmail.com <mailto:jtbandes@gmail.com>> wrote:

I like this idea, but the syntax seems dangerously close to a call site for "func *(lhs: Int, rhs: Any.Type)" (which is obviously ill-advised, but it is allowed).

Maybe we could take advantage of something which would be very invalid under the current grammar, namely (n T) rather than (n * T):

   let values: (4 Int) = (1, 2, 3, 4)

Sure, or we could lift (4 x Int) from LLVM IR's syntax.

How about:

  let values:Int[4] = (1,2,3,4)

While it looks a bit like a subscript, it doesn’t make sense in a type declaration at present, so could be a good way to define restrictions of this type (we could even extend it to collections later). If the similarity is too close then:

  let values:(Int[4]) = (1,2,3,4)

Could work too? Just some alternatives anyway, as I like the idea.

This kind of syntax doesn't compose well with other type productions. If you parse Int[N][M] naively as (Int[N])[M], then you end up with an array of M (array of N (Int)), which ends up subscripting in the opposite order, array[0..<M][0..<N]. C works around this by flipping the order of multiple array indices in a type declaration, so int [n][m] is really (int [m]) [n], but this doesn't work well for Swift, which has other postfix type productions—how would Int[N]?[M] parse? Choosing a prefix notation for fixed-sized array bounds is better IMO to avoid these pitfalls.

-Joe

_______________________________________________
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

--
Trent Nadeau

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

+1 for the proposal, and +1 for Nate's syntax.

What about "(n of Type)"?

Sent from my iPhone, please excuse brevity and errors

That is currently true, but it might not always be the case. In principle it's possible to write a compile-time function (I think "macro" is the word I'm looking for) that operates solely on types, rather than values, and could be evaluated at compile time. Why adopt a syntax that's likely to conflict with a commonly requested feature?

···

On Jan 28, 2016, at 19:36, Nate Birkholz via swift-evolution <swift-evolution@swift.org> wrote:

On Jan 28, 2016, at 7:32 PM, Félix Cloutier via swift-evolution <swift-evolution@swift.org> wrote:

[...] Operators can't appear inside a type, so I don't think that it would be a problem to reuse * there either.

- Dave Sweeris

# Fixed Sized Arrays

* Proposal: TBD
* Author(s): [Swift Developer](https://github.com/swiftdev\)
* Status: **Awaiting review**
* Review manager: TBD

## Introduction

To provide better support for C static arrays and to help implement low level memory concious data structures, it would be helpful to add a new syntax to define fixed sized arrays of a single type in Swift.

Swift-evolution thread: [Proposal: Contiguous Variables (A.K.A. Fixed Sized Array Type)](https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160125/007984.html\)

## Motivation

While Swift does allow for arrays and tuples with repeating instances of the same type, both do not map well to low level structures like C static arrays. It would be beneficial to provide a type with a closer mapping the the semantics and capabilities of C static arrays to help with interfacing with low level libraries and hardware (like GPU rendering data). While this can be accomplished in Swift currently it is awkward. Also most languages have some form of fixed size array and it's lacking in Swift has become more and more noticeable.

## Proposed solution

It should be possible to take the current existing mapping from C static arrays to tuples and modify it slightly to help round out the feature. Changes to tuples would include a new syntax for defining fixed size arrays (shown below), adding subscripting to tuples, and providing a way to initialize this new form of tuple. To prevent confusion between standard tuples and fixed array tuples, only tuples that have no element labels and that have all the same element type would be allowed to be subscripted.

The syntax to declare a fixed size array would be as follows:

    var values: (4 x Int)
  
The declaration would be surrounded by parenthesis similar to an existing tuple type, but the size of the array would be given first followed by the type of the elements of the array. The declaration given here would specify four consecutive Int values similar to the tuple `(Int, Int, Int, Int)`.

Initializing the individual elements of a fixed array would be similar to initialzing an existing tuple:

    let values: (4 x Int) = (1, 2, 3, 4)

Initializing all the elements to a single value would be done similar to calling an initializer on a type:

    let values: (4 x Int)(repeatedValue: 0) // Is this possible?

Instead of accessing individual elements of a tuple using index numbers such as `value.0` and `value.1` fixed size arrays will be indexed similar to normal arrays using normal subscript syntax `values[0]`.

## Detailed design

TBD

## Impact on existing code

As this would be a change in how static arrays from C are imported into Swift, any existing code using that feature would break due to the change in how to access the elements of the array. Applications making use of static C arrays would need to be recompiled and migrated to use newer syntax. If the decision is make to allow for both forms of indexing then no code would break due to this change and authors could migrate their code as needed to the new syntax.

## Alternatives considered

Using tuples as they are implement now does provide access to C static arrays and to write data structures with memory layouts similar to C static arrays, but it is not a very elegant solution. If fixed arrays can be added to the language easily then it would be well worth it to improve Swift with the same functionality that is normally found in most system level languages.

···

On Jan 28, 2016, at 10:23 PM, Justin Kolb <justin.kolb@gmail.com> wrote:

I will make an attempt at a first draft given what I’ve read in this thread. I’m a little fuzzy on how to proceed as the process document makes mention of using the template and getting refinements on the mailing list before making a PR with the proposal. I have been having trouble finding examples of that in prior threads. Should I post the initial markdown to the thread?

On Jan 28, 2016, at 9:57 PM, Chris Lattner <clattner@apple.com <mailto:clattner@apple.com>> wrote:

On Jan 28, 2016, at 5:07 PM, Erica Sadun via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

I find

let values: (4 x Int) = (1, 2, 3, 4)

to be adequately cromulent. I believe this approach to be:

* Readable, even to someone unfamiliar with the syntax
* The parens before the assignment suggest something to do with tuples, and the numbers match the arity after the assignment
* The type is preserved in-place
* It's compact, elegant, simple

+1. I like this syntax too, and with Joe’s other proposed extensions, it would all fit together nicely. Anyone interested in writing up a proposal?

-Chris

-- E

On Jan 28, 2016, at 5:56 PM, Joe Groff via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Jan 28, 2016, at 4:04 PM, Haravikk <e-mail@haravikk.me <mailto:e-mail@haravikk.me>> wrote:

On 28 Jan 2016, at 22:37, Joe Groff via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Jan 28, 2016, at 2:36 PM, Jacob Bandes-Storch <jtbandes@gmail.com <mailto:jtbandes@gmail.com>> wrote:

I like this idea, but the syntax seems dangerously close to a call site for "func *(lhs: Int, rhs: Any.Type)" (which is obviously ill-advised, but it is allowed).

Maybe we could take advantage of something which would be very invalid under the current grammar, namely (n T) rather than (n * T):

   let values: (4 Int) = (1, 2, 3, 4)

Sure, or we could lift (4 x Int) from LLVM IR's syntax.

How about:

  let values:Int[4] = (1,2,3,4)

While it looks a bit like a subscript, it doesn’t make sense in a type declaration at present, so could be a good way to define restrictions of this type (we could even extend it to collections later). If the similarity is too close then:

  let values:(Int[4]) = (1,2,3,4)

Could work too? Just some alternatives anyway, as I like the idea.

This kind of syntax doesn't compose well with other type productions. If you parse Int[N][M] naively as (Int[N])[M], then you end up with an array of M (array of N (Int)), which ends up subscripting in the opposite order, array[0..<M][0..<N]. C works around this by flipping the order of multiple array indices in a type declaration, so int [n][m] is really (int [m]) [n], but this doesn't work well for Swift, which has other postfix type productions—how would Int[N]?[M] parse? Choosing a prefix notation for fixed-sized array bounds is better IMO to avoid these pitfalls.

-Joe

_______________________________________________
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

I think that (4 x Int) needs to be syntax sugar for (Int, Int, Int, Int). Not having them the same would introduce awkward cases into the language.

Because of that, I also think that forcing people to use the subscript would have some awkward consequences. What if I have a func<T, U> that uses a (T, U) tuple and both T and U happen to be the same type?

So I think that tuples whose elements all have the same type should get a subscript but shouldn't lose direct field access. This would also avoid breaking existing code, and place the bounds check at compile-time instead of runtime. (The compiler will tell you if you try to access foo.4 on a (4 x Int) tuple, but it likely won't if you try to access foo[4]).

Félix

···

Le 29 janv. 2016 à 00:18:43, Justin Kolb <justin.kolb@gmail.com> a écrit :

# Fixed Sized Arrays

* Proposal: TBD
* Author(s): [Swift Developer](https://github.com/swiftdev\)
* Status: **Awaiting review**
* Review manager: TBD

## Introduction

To provide better support for C static arrays and to help implement low level memory concious data structures, it would be helpful to add a new syntax to define fixed sized arrays of a single type in Swift.

Swift-evolution thread: [Proposal: Contiguous Variables (A.K.A. Fixed Sized Array Type)](https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160125/007984.html\)

## Motivation

While Swift does allow for arrays and tuples with repeating instances of the same type, both do not map well to low level structures like C static arrays. It would be beneficial to provide a type with a closer mapping the the semantics and capabilities of C static arrays to help with interfacing with low level libraries and hardware (like GPU rendering data). While this can be accomplished in Swift currently it is awkward. Also most languages have some form of fixed size array and it's lacking in Swift has become more and more noticeable.

## Proposed solution

It should be possible to take the current existing mapping from C static arrays to tuples and modify it slightly to help round out the feature. Changes to tuples would include a new syntax for defining fixed size arrays (shown below), adding subscripting to tuples, and providing a way to initialize this new form of tuple. To prevent confusion between standard tuples and fixed array tuples, only tuples that have no element labels and that have all the same element type would be allowed to be subscripted.

The syntax to declare a fixed size array would be as follows:

    var values: (4 x Int)
  
The declaration would be surrounded by parenthesis similar to an existing tuple type, but the size of the array would be given first followed by the type of the elements of the array. The declaration given here would specify four consecutive Int values similar to the tuple `(Int, Int, Int, Int)`.

Initializing the individual elements of a fixed array would be similar to initialzing an existing tuple:

    let values: (4 x Int) = (1, 2, 3, 4)

Initializing all the elements to a single value would be done similar to calling an initializer on a type:

    let values: (4 x Int)(repeatedValue: 0) // Is this possible?

Instead of accessing individual elements of a tuple using index numbers such as `value.0` and `value.1` fixed size arrays will be indexed similar to normal arrays using normal subscript syntax `values[0]`.

## Detailed design

TBD

## Impact on existing code

As this would be a change in how static arrays from C are imported into Swift, any existing code using that feature would break due to the change in how to access the elements of the array. Applications making use of static C arrays would need to be recompiled and migrated to use newer syntax. If the decision is make to allow for both forms of indexing then no code would break due to this change and authors could migrate their code as needed to the new syntax.

## Alternatives considered

Using tuples as they are implement now does provide access to C static arrays and to write data structures with memory layouts similar to C static arrays, but it is not a very elegant solution. If fixed arrays can be added to the language easily then it would be well worth it to improve Swift with the same functionality that is normally found in most system level languages.

On Jan 28, 2016, at 10:23 PM, Justin Kolb <justin.kolb@gmail.com <mailto:justin.kolb@gmail.com>> wrote:

I will make an attempt at a first draft given what I’ve read in this thread. I’m a little fuzzy on how to proceed as the process document makes mention of using the template and getting refinements on the mailing list before making a PR with the proposal. I have been having trouble finding examples of that in prior threads. Should I post the initial markdown to the thread?

On Jan 28, 2016, at 9:57 PM, Chris Lattner <clattner@apple.com <mailto:clattner@apple.com>> wrote:

On Jan 28, 2016, at 5:07 PM, Erica Sadun via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

I find

let values: (4 x Int) = (1, 2, 3, 4)

to be adequately cromulent. I believe this approach to be:

* Readable, even to someone unfamiliar with the syntax
* The parens before the assignment suggest something to do with tuples, and the numbers match the arity after the assignment
* The type is preserved in-place
* It's compact, elegant, simple

+1. I like this syntax too, and with Joe’s other proposed extensions, it would all fit together nicely. Anyone interested in writing up a proposal?

-Chris

-- E

On Jan 28, 2016, at 5:56 PM, Joe Groff via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Jan 28, 2016, at 4:04 PM, Haravikk <e-mail@haravikk.me <mailto:e-mail@haravikk.me>> wrote:

On 28 Jan 2016, at 22:37, Joe Groff via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Jan 28, 2016, at 2:36 PM, Jacob Bandes-Storch <jtbandes@gmail.com <mailto:jtbandes@gmail.com>> wrote:

I like this idea, but the syntax seems dangerously close to a call site for "func *(lhs: Int, rhs: Any.Type)" (which is obviously ill-advised, but it is allowed).

Maybe we could take advantage of something which would be very invalid under the current grammar, namely (n T) rather than (n * T):

   let values: (4 Int) = (1, 2, 3, 4)

Sure, or we could lift (4 x Int) from LLVM IR's syntax.

How about:

  let values:Int[4] = (1,2,3,4)

While it looks a bit like a subscript, it doesn’t make sense in a type declaration at present, so could be a good way to define restrictions of this type (we could even extend it to collections later). If the similarity is too close then:

  let values:(Int[4]) = (1,2,3,4)

Could work too? Just some alternatives anyway, as I like the idea.

This kind of syntax doesn't compose well with other type productions. If you parse Int[N][M] naively as (Int[N])[M], then you end up with an array of M (array of N (Int)), which ends up subscripting in the opposite order, array[0..<M][0..<N]. C works around this by flipping the order of multiple array indices in a type declaration, so int [n][m] is really (int [m]) [n], but this doesn't work well for Swift, which has other postfix type productions—how would Int[N]?[M] parse? Choosing a prefix notation for fixed-sized array bounds is better IMO to avoid these pitfalls.

-Joe

_______________________________________________
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

Damn, I'm way to slow writing proposals…

I have one big problem with using tuples as basis for fixed-size vectors:
They cannot have methods, and I want a matrix-type to have some of those.

Have a look at

if you want to see what I'd prefer instead — hopefully, I can spare an hour or two today to finish the text.

Tino

+1 from me, for "principle of least surprise" and "principle of not making the type checker do extra work".

Jordan

···

On Jan 28, 2016, at 20:00, Chris Lattner via swift-evolution <swift-evolution@swift.org> wrote:

On Jan 28, 2016, at 7:57 PM, Chris Lattner <clattner@apple.com <mailto:clattner@apple.com>> wrote:

On Jan 28, 2016, at 5:07 PM, Erica Sadun via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

I find

let values: (4 x Int) = (1, 2, 3, 4)

to be adequately cromulent. I believe this approach to be:

* Readable, even to someone unfamiliar with the syntax
* The parens before the assignment suggest something to do with tuples, and the numbers match the arity after the assignment
* The type is preserved in-place
* It's compact, elegant, simple

+1. I like this syntax too, and with Joe’s other proposed extensions, it would all fit together nicely. Anyone interested in writing up a proposal?

One other tweak worth considering: instead of subscript being defined on a tuple as returning a common type, a more modest proposal would be that subscript is defined on tuples that:

a) have no element labels.
b) all have the same element type.

This would solve the fixed size array use-case, be much easier to implement, and not have surprising performance issues promoting things to Any. It is also consistent with the fact that we don’t infer the type of [Int(), Float()] to [Any].

Sure. What do you think about special-casing subscripting by integer literal? We could potentially supersede the 'x.0' syntax with 'x[0]', giving an integer literal subscript the added power to produce the Nth value as the Nth concrete type of the tuple.

-Joe

···

On Jan 28, 2016, at 9:49 PM, Chris Lattner <clattner@apple.com> wrote:

On Jan 28, 2016, at 9:25 PM, Joe Groff <jgroff@apple.com <mailto:jgroff@apple.com>> wrote:

+1. I like this syntax too, and with Joe’s other proposed extensions, it would all fit together nicely. Anyone interested in writing up a proposal?

One other tweak worth considering: instead of subscript being defined on a tuple as returning a common type, a more modest proposal would be that subscript is defined on tuples that:

a) have no element labels.
b) all have the same element type.

This would solve the fixed size array use-case, be much easier to implement, and not have surprising performance issues promoting things to Any. It is also consistent with the fact that we don’t infer the type of [Int(), Float()] to [Any].

I'm not sure this prevents anything, since labeled tuples implicitly convert to unlabeled tuples, and tuples support structural subtyping, so (Derived, Derived) is-a (Base, Base) is-an (Any, Any). Both of those type rules might be worth reconsidering on their own, of course, but otherwise you could still backdoor your way into subscripting a heterogeneous and/or labeled tuple via those conversions.

Right, I’d much rather see:
  let v = (someHeterogenousTuple as (4 x Any))[i]
Rather than:
  let v = someHeterogenousTuple[i]

given that the subscripting syntax is intended to be an efficient “array index” operation. I’m uncomfortable with an expensive representation-transforming operation that potentially involves heap allocation (when the tuple element is a struct larger than the Any existential rep) happening accidentally.

That said, perhaps there is a middle ground: we can use the same rules we use for array literals since array literals also don’t merge to Any as their common type. I see no concerns with using the common type for a heterogenous tuple of classes that have a common base class, for example, because that won’t be a representation change.

That said, I don’t think this will be a very important use case, so I’d be happy with subsetting that out of the base proposal, and adding it when there is a specific motivation for it.

(Sorry to go so far back… I started replying to this on probably the 29th and somehow forgot about it.)

Out of curiosity, why would the subscript of non-homogeneous tuple have to return an "Any”? If we declare this:
let grohl = (0, “foo”, “fighters”, 0.0)

Why couldn’t subscript (and $0 in map, for that matter) return a type that’s the “intersection” of Int, String, and Double?
// compiler expands this to (grohl.0.hashValue, grohl.1.hashValue, grohl.2.hashValue, grohl.3.hashValue)
let thatsJustCrazyTalk = grohl.map {$0.hashValue} // no error because Int, String, and Double all have a hashValue property…

It seems to me that figuring out what’s legal for $0 wouldn’t be that hard… I mean, at the risk of publicizing my ignorance regarding the compiler’s internal workings, in my head, at least, the compiler maintains a set of valid functions/properties for each type, and $0’s set would literally just be the intersection of the sets associated with the types in the tuple.

Is it way more complicated than that? (One of these days I’m going to figure out how LLVM works so that I won’t have ask questions like that.)

- Dave Sweeris

···

On Jan 28, 2016, at 20:00, Chris Lattner via swift-evolution <swift-evolution@swift.org> wrote:

On Jan 28, 2016, at 7:57 PM, Chris Lattner <clattner@apple.com <mailto:clattner@apple.com>> wrote:

On Jan 28, 2016, at 5:07 PM, Erica Sadun via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

I find

let values: (4 x Int) = (1, 2, 3, 4)

to be adequately cromulent. I believe this approach to be:

* Readable, even to someone unfamiliar with the syntax
* The parens before the assignment suggest something to do with tuples, and the numbers match the arity after the assignment
* The type is preserved in-place
* It's compact, elegant, simple

+1. I like this syntax too, and with Joe’s other proposed extensions, it would all fit together nicely. Anyone interested in writing up a proposal?

One other tweak worth considering: instead of subscript being defined on a tuple as returning a common type, a more modest proposal would be that subscript is defined on tuples that:

a) have no element labels.
b) all have the same element type.

This would solve the fixed size array use-case, be much easier to implement, and not have surprising performance issues promoting things to Any. It is also consistent with the fact that we don’t infer the type of [Int(), Float()] to [Any].

-Chris

What is a "type-level integer expression"? The only thing I can think of is allowing numeric parameters to generics, like "Tuple<4, Int>", but I don't think that's what you're talking about.

That's what I mean, yeah. If we allow integers as type parameters, you'd conceivably want to use integer literals and expressions in this position too.

-Joe

···

On Jan 28, 2016, at 2:40 PM, Jacob Bandes-Storch <jtbandes@gmail.com> wrote:

Jacob

On Thu, Jan 28, 2016 at 2:38 PM, Joe Groff <jgroff@apple.com <mailto:jgroff@apple.com>> wrote:

> On Jan 28, 2016, at 2:37 PM, Joe Groff <jgroff@apple.com <mailto:jgroff@apple.com>> wrote:
>
>
>> On Jan 28, 2016, at 2:36 PM, Jacob Bandes-Storch <jtbandes@gmail.com <mailto:jtbandes@gmail.com>> wrote:
>>
>> I like this idea, but the syntax seems dangerously close to a call site for "func *(lhs: Int, rhs: Any.Type)" (which is obviously ill-advised, but it is allowed).
>>
>> Maybe we could take advantage of something which would be very invalid under the current grammar, namely (n T) rather than (n * T):
>>
>> let values: (4 Int) = (1, 2, 3, 4)

Bare juxtaposition might be problematic if we ever do introduce type-level integer expressions, though.

-Joe

I think that (4 x Int) needs to be syntax sugar for (Int, Int, Int, Int). Not having them the same would introduce awkward cases into the language.

Agreed. This means that:

   let values: (4 x Int)(repeatedValue: 0) // Is this possible?

will not be possible.

Because of that, I also think that forcing people to use the subscript would have some awkward consequences. What if I have a func<T, U> that uses a (T, U) tuple and both T and U happen to be the same type?

I don’t understand this concern.

So I think that tuples whose elements all have the same type should get a subscript but shouldn't lose direct field access.

Agreed.

-Chris

···

On Jan 28, 2016, at 9:41 PM, Félix Cloutier <felixcca@yahoo.ca> wrote:

Same here, but can’t we wrap them?
struct Vector<(4 x T) where T: MathType> {}

- Dave Sweeris

···

On Jan 29, 2016, at 01:01, Tino Heth via swift-evolution <swift-evolution@swift.org> wrote:

Damn, I'm way to slow writing proposals…

I have one big problem with using tuples as basis for fixed-size vectors:
They cannot have methods, and I want a matrix-type to have some of those.

Have a look at
Compile time parameters · SwiftInofficialEvolution/Home Wiki · GitHub
if you want to see what I'd prefer instead — hopefully, I can spare an hour or two today to finish the text.

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

I think that (4 x Int) needs to be syntax sugar for (Int, Int, Int, Int). Not having them the same would introduce awkward cases into the language.

Yes, they should be different spellings of the same type.

Because of that, I also think that forcing people to use the subscript would have some awkward consequences. What if I have a func<T, U> that uses a (T, U) tuple and both T and U happen to be the same type?

Statically we have to assume that's a heterogenous tuple. Indexing would either produce Any or be disallowed, depending on the design.

-Joe

···

On Jan 28, 2016, at 9:41 PM, Félix Cloutier <felixcca@yahoo.ca> wrote:

Damn, I'm way to slow writing proposals…

I have one big problem with using tuples as basis for fixed-size vectors:
They cannot have methods, and I want a matrix-type to have some of those.

If we go with this design, the canonical way to do that is as a struct wrapping a tuple, something like:

struct Matrix4x4 {
  private var elements : (4 x (4 x Float))

  public func …
}

This seems like a nice way to handle it, keeping the balance of not adding a completely new fundamental type to the language to solve such a narrow case.

-Chris

···

On Jan 29, 2016, at 1:01 AM, Tino Heth via swift-evolution <swift-evolution@swift.org> wrote:

Have a look at
Compile time parameters · SwiftInofficialEvolution/Home Wiki · GitHub
if you want to see what I'd prefer instead — hopefully, I can spare an hour or two today to finish the text.

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

Same here, but can’t we wrap them?
struct Vector<(4 x T) where T: MathType> {}

Might be possible, but I guess it will be much work:
You can't declare something like

class A<Array<T> where T is SequenceType>

now.

Also, I have an aversion of mixing the concept of array and tuple — and am I the only one who get creeps because of that "x" in the declaration? I hope this is just a placeholder — either for a sigil yet to be found (maybe something like ":", "@"), or for the whole syntax.

Tino

I think that (4 x Int) needs to be syntax sugar for (Int, Int, Int, Int). Not having them the same would introduce awkward cases into the language.

Agreed. This means that:

  let values: (4 x Int)(repeatedValue: 0) // Is this possible?

will not be possible.

Why will it be possible to add a subscript but not an initializer?

Because of that, I also think that forcing people to use the subscript would have some awkward consequences. What if I have a func<T, U> that uses a (T, U) tuple and both T and U happen to be the same type?

I don’t understand this concern.

If direct element access is disallowed on homogeneous tuples, to me, it would look like a bug that you can use direct element access on a (T, U) tuple from a generic function with <T, U> parameters, but not anywhere else. But regardless, we seem to agree that homogeneous tuples shouldn't lose direct member access.

Félix

···

Le 29 janv. 2016 à 00:50:52, Chris Lattner <clattner@apple.com> a écrit :

On Jan 28, 2016, at 9:41 PM, Félix Cloutier <felixcca@yahoo.ca> wrote:

I think that (4 x Int) needs to be syntax sugar for (Int, Int, Int,
Int). Not having them the same would introduce awkward cases into
the language.

Agreed. This means that:

   let values: (4 x Int)(repeatedValue: 0) // Is this possible?

will not be possible.

I think this avenue leaves some really crucial use-cases on the table,
e.g. implementing bounded-size dynamically-growable arrays. There
should, at the very least, be a way to declare an array of uninitialized
suitably-aligned storage for any type. And I think we'd also need
non-type generic parameters to complete the picture.

···

on Thu Jan 28 2016, Chris Lattner <swift-evolution@swift.org> wrote:

On Jan 28, 2016, at 9:41 PM, Félix Cloutier <felixcca@yahoo.ca> wrote:

Because of that, I also think that forcing people to use the
subscript would have some awkward consequences. What if I have a
func<T, U> that uses a (T, U) tuple and both T and U happen to be
the same type?

I don’t understand this concern.

So I think that tuples whose elements all have the same type should
get a subscript but shouldn't lose direct field access.

Agreed.

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

--
-Dave

Personally, I wouldn’t be thrilled with that directly. This would make tuple accesses more “array like” than “struct like”. For heterogenous tuples, they are unquestionably more struct like.

I feel like adding the subscript only in the case of homogenous tuples nicely splits the different here, and it seems like it would fit better into the generics model (though I’m much less sure about that).

-Chris

···

On Jan 29, 2016, at 11:20 AM, Joe Groff <jgroff@apple.com> wrote:

given that the subscripting syntax is intended to be an efficient “array index” operation. I’m uncomfortable with an expensive representation-transforming operation that potentially involves heap allocation (when the tuple element is a struct larger than the Any existential rep) happening accidentally.

That said, perhaps there is a middle ground: we can use the same rules we use for array literals since array literals also don’t merge to Any as their common type. I see no concerns with using the common type for a heterogenous tuple of classes that have a common base class, for example, because that won’t be a representation change.

That said, I don’t think this will be a very important use case, so I’d be happy with subsetting that out of the base proposal, and adding it when there is a specific motivation for it.

Sure. What do you think about special-casing subscripting by integer literal? We could potentially supersede the 'x.0' syntax with 'x[0]', giving an integer literal subscript the added power to produce the Nth value as the Nth concrete type of the tuple.

Swift has no such intersection type. The closes analogs we have are Any (or if you allow boxing, NSObject/NSValue).

-Chris

···

On Feb 9, 2016, at 11:33 AM, davesweeris@mac.com wrote:

This would solve the fixed size array use-case, be much easier to implement, and not have surprising performance issues promoting things to Any. It is also consistent with the fact that we don’t infer the type of [Int(), Float()] to [Any].

-Chris

(Sorry to go so far back… I started replying to this on probably the 29th and somehow forgot about it.)

Out of curiosity, why would the subscript of non-homogeneous tuple have to return an "Any”? If we declare this:
let grohl = (0, “foo”, “fighters”, 0.0)

Why couldn’t subscript (and $0 in map, for that matter) return a type that’s the “intersection” of Int, String, and Double?