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

The advantage in going with a "only allow a single member of type T that initializes across the entire tuple" is that it enforces safety and simplicity.

-- E

···

On Jan 29, 2016, at 11:43 AM, Joe Groff via swift-evolution <swift-evolution@swift.org> wrote:

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

To me, it's closely related to the declaration issue. By introducing a (N x Type) syntax, we're solving the LHS problem but leaving the RHS problem intact. If we want to spin it off into a separate proposal, I think that the most logical split is to have a proposal for subscripts on uniform tuples, and a a proposal for the shorthand syntax and a way to initialize values of these types.

Just spitballing…we could bring the N x <expr> syntax to expressions as well, so that (5 x 0) is (0,0,0,0,0), and maybe (1, 3 x 0, 2) is (1, 0, 0, 0, 2). With integer literals it's hard to tell which side is which, though...

-Joe

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

How about:
  FixedSizeBuffer(0)

We introduce initializer expression syntax for tuples that takes an element, and define it to be a splat in the case of a homogenous tuple, or an error if not.

-Chris

···

On Jan 29, 2016, at 11:23 AM, Jordan Rose via swift-evolution <swift-evolution@swift.org> wrote:

On Jan 29, 2016, at 10:43, Joe Groff via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

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

To me, it's closely related to the declaration issue. By introducing a (N x Type) syntax, we're solving the LHS problem but leaving the RHS problem intact. If we want to spin it off into a separate proposal, I think that the most logical split is to have a proposal for subscripts on uniform tuples, and a a proposal for the shorthand syntax and a way to initialize values of these types.

Just spitballing…we could bring the N x <expr> syntax to expressions as well, so that (5 x 0) is (0,0,0,0,0), and maybe (1, 3 x 0, 2) is (1, 0, 0, 0, 2). With integer literals it's hard to tell which side is which, though...

Throwing out some possibilities:

var buffer: FixedSizeBuffer = (0...)
var buffer: FixedSizeBuffer = (* x 0)
var buffer: FixedSizeBuffer = (repeat 0)

The fact that this could be used in expressions is making the N x T syntax
grow on me.

(N x T) := (T, T, ...)
(N x <expr>) := (<expr>, <expr>, ...)

It has a nice symmetry.

···

On Fri, Jan 29, 2016 at 1:43 PM, Joe Groff via swift-evolution < swift-evolution@swift.org> wrote:

> On Jan 28, 2016, at 9:24 PM, Félix Cloutier <felixcca@yahoo.ca> wrote:
>
> To me, it's closely related to the declaration issue. By introducing a
(N x Type) syntax, we're solving the LHS problem but leaving the RHS
problem intact. If we want to spin it off into a separate proposal, I think
that the most logical split is to have a proposal for subscripts on uniform
tuples, and a a proposal for the shorthand syntax and a way to initialize
values of these types.

Just spitballing…we could bring the N x <expr> syntax to expressions as
well, so that (5 x 0) is (0,0,0,0,0), and maybe (1, 3 x 0, 2) is (1, 0, 0,
0, 2). With integer literals it's hard to tell which side is which,
though...

-Joe

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

--
Trent Nadeau

Speaking of spitballing, these can be nested/composed, right?
let x = (3 x (0, 2 x “”), 2 x NSFileManager())

Looks like there’s a missing set of parenthesis. I would expect:

let x = ((3 x (0, 2 x “”)), (2 x NSFileManager()))

To gives these result

So, I think that this would be correct:
let x0 = x.0 // is ((Int, (String, String)), (Int, (String, String)), (Int, (String, String)))
let x1 = x.1 // is (NSFileManager, NSFileManager)
let xIdx0 = x.0[0] // is (Int, (String, String))

Can we implicitly “unzip” the implicit "arrays”, as well?
let x00 = x.0.0 // is (Int, Int, Int)… equivalent to let x00 = x.0.map { $0.0 }
let x01 = x.0.1 // is ((String, String), (String, String), (String, String))… equivalent to let x01 = x.0.map { $0.1 }

As for the original
let x = (3 x (0, 2 x “”), 2 x NSFileManager())

The results would be:
let x0 = x.0 // is (Int, (String, String)
let x3 = x.3 // is NSFileManager
let xIdx0 = x.0[0] // is Int

Dany

···

Le 29 janv. 2016 à 14:13, Dave via swift-evolution <swift-evolution@swift.org> a écrit :

On Jan 29, 2016, at 10:43, Joe Groff via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

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

To me, it's closely related to the declaration issue. By introducing a (N x Type) syntax, we're solving the LHS problem but leaving the RHS problem intact. If we want to spin it off into a separate proposal, I think that the most logical split is to have a proposal for subscripts on uniform tuples, and a a proposal for the shorthand syntax and a way to initialize values of these types.

Just spitballing…we could bring the N x <expr> syntax to expressions as well, so that (5 x 0) is (0,0,0,0,0), and maybe (1, 3 x 0, 2) is (1, 0, 0, 0, 2). With integer literals it's hard to tell which side is which, though...

-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
https://lists.swift.org/mailman/listinfo/swift-evolution

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

-Joe

···

On Jan 28, 2016, at 2:37 PM, Joe Groff <jgroff@apple.com> 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)

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.

···

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.

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.

Jacob

···

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

> On Jan 28, 2016, at 2:37 PM, Joe Groff <jgroff@apple.com> 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)

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

-Joe

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

···

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

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 <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
https://lists.swift.org/mailman/listinfo/swift-evolution

I don't like how similar-but-not-quite-the-same it is as the array declaration syntax. That would make it Int[4] for a fixed-size array and [Int] for an array of dynamic size.

I like that (4 x Int) is inside parentheses, which is code for "tuple" right now.

Related question: can you initialize a uniform tuple/contiguous variable with an array literal?

Félix

···

Le 28 janv. 2016 à 19:04:50, Haravikk via swift-evolution <swift-evolution@swift.org> a écrit :

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.
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

What about (n of Type)?

···

Sent from my iPhone, please excuse brevity and errors

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

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

_______________________________________________
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

What about "(n of Type)"?

···

Sent from my iPhone, please excuse brevity and errors

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

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

_______________________________________________
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

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

···

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

-- 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
https://lists.swift.org/mailman/listinfo/swift-evolution

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

···

On Jan 28, 2016, at 7: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?

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

I don't think this is an issue. Practically speaking, there isn't anything we could do layout-wise for a homogeneous tuple in memory that would be better than a contiguous array.

-Joe

···

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

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

-Joe

···

On Jan 28, 2016, at 8:00 PM, Chris Lattner <clattner@apple.com> 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].

That is good to hear as it should be easier to implement this feature then. I didn’t realize yet that C structs with arrays were imported like that, it helps me with the decision to settle with option 2 for now in the code I was planning to write.

I would expect that `0` would not be allowed for type declarations.

···

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

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 <mailto: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 <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

Hmm… Two dimensions tuples...
let matrix: (2 (4 Int)) = ( (1,2,3,4), (5,6,7,8) )
print(matrix.0.0, matrix.1.3) // display 1 and 8
// Output based on let matrix = ((1,2,3,4), (5,6,7,8))

The type is easier to read with LLVM IR syntax mentioned by Joe
let matrix: (2 x (4 x Int)) = ( (1,2,3,4), (5,6,7,8) )

A one dimensional tuple is supposed to be contiguous, but does the same behaviour apply to tuples of tuples?

Dany

···

Le 28 janv. 2016 à 19:56, Joe Groff via swift-evolution <swift-evolution@swift.org> a écrit :

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.

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.

-Chris

···

On Jan 28, 2016, at 9:25 PM, Joe Groff <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.