[swift-evolution] [Pitch] New Version of Array Proposal
darylew at mac.com
Sun Jul 23 22:05:08 CDT 2017
> On Jul 23, 2017, at 12:04 PM, Taylor Swift <kelvin13ma at gmail.com> wrote:
> On Sun, Jul 23, 2017 at 3:08 AM, Daryle Walker <darylew at mac.com <mailto:darylew at mac.com>> wrote:
>> 9. I don’t see the value in having both nested FSAs and multi-dimensional FSAs. Aren’t they the same thing? For example, in the code snippet
> Why does any language with multi-dimensional arrays (like Fortran or Ada) have them? By this standard, no language should have multi-dimensional arrays. They exist because of data modeling. Co-equal coordinates in the model should be co-equal in their representation in the program. Yes, they are implemented the same way underneath. We don’t copy C everywhere, so why not take this opportunity to do better. Also, just using nesting could imply that the intermediate array types have a meaning, but they might not if they’re just implementation quirks and not part of the abstract model.
> Nested arrays are not my solution for multi-coordinate indexing; use multi-dimensional arrays for that. I mention nested arrays because:
> Nested arrays fundamentally cannot be banned. (What if an element type is hidden behind a type-alias and is conditionally an array type?)
> Doesn’t Swift have to resolve the types at some point anyway? If it’s impossible to ban, we can allow it, but still make it unidiomatic. Nested arrays are much messier to write than multidimensional arrays.
The new draft I’m writing downplays nested arrays a lot. They’re mentioned in the section discussing the core element type (nee the inner non-array type).
> I need the definition to explain the “inner non-array type”
> I need the inner non-array type to explain which pairings of FSAs for reshaping are legal. (And a similar reason for tuple conversion.) Note the two types can have different nesting levels.
> I need to explain that empty arrays cannot be an array element type. (Should this be changed? What happens with tuples or structures containing empty tuples/structures as members? What about empty tuples/sturctures in “Array”? Banning empty arrays means we don’t have to worry about every array element being at the same address. The other way to solve this is to make them one byte (or word) long.)
>> let a = [;1, 2, 3, 4]
>> assert(a == 1)
>> assert(a == 2)
>> assert(a == 3)
>> assert(a == 4)
>> let b = a as [2, 2; Int]
>> assert(b[0, 0] == 1)
>> assert(b[0, 1] == 2)
>> assert(b[1, 0] == 3)
>> assert(b[1, 1] == 4)
>> let c = a as [2; [2; Int]]
>> assert(c == 1)
>> assert(c == 2)
>> assert(c == 3)
>> assert(c == 4)
>> There’s three syntaxes which accomplish two unique things. I lean towards disallowing FSA nesting and instead allowing incomplete index lists to partially unnest multidimensional FSAs. Let’s reserve “...” for flexible array chained dereferencing.
> I don’t understand what your incomplete index list idea is. And as I said, the chaining technique is less I desire it and more I can’t ban it and keep Swift features orthogonal.
> Incomplete indexing means
> let fsa:[5, 2; Int] = [5, 2; 2, 4, 3, 5, 4, 6, 5, 7, 6, 8]
> fsa // [2; 5, 7]
> this would be the same as writing
> let fsa:[5; [2; Int]] = [5; [2; 2, 4], [2; 3, 5], [2; 4, 6], [2; 5, 7], [2; 6, 8]]
> fsa // [2; 5, 7]
> in your current system. This would obviate the need to nest FSAs for the purpose of extracting entire rows of data.
Allowing partial indexing as you show it privileges one dimension over the others, although they’re supposed to be co-equal and the reason a particular dimension is privileged is due to an implementation detail. Or would you allow incomplete indexing on other dimensions besides the first? Where the true-multi-dimensional <-> nested FSA equivalence wouldn’t help you (because the elements are dispersed in the whole array). With complete generics, this could be a library function:
func removeRow<Dimension: Int, M…: Int, N…: Int, P: Int, T>(array: […M, P, …N; T], row: Int) -> […M, …N; T] where #lengthof(M) == Dimension
>> 11. This should have defined behavior:
>> let data = [2, 2; 1, 2, 4, 8]
>> for (i, x) in data.enumerated()
>> total += x
> FSAs are compound types, not named types, so there are no methods. (Just like tuples, FSAs don’t follow any protocols.) But since they’re a built-in, I can customize the “for-in” loop to cover all the elements in an implementation-optimized order. (The implementation has the option of multi-threading if it can see there’s no cross-iteration contamination.) Since you can’t control the order without manual looping, the “#indexOf” expression exists to let you know where you are during an iteration loop.
> I first used the iteration variable as the operand to “#indexOf” to determine which array instance to track. Then I saw that the for-loop implements its iteration variable as a pattern in the grammar instead of something simpler. And what happens if a wildcard is used as the iteration variable? And would people question why when the pattern has multiple iteration variables, all are equally valid for “#indexOf”? I moved the operand to be the label because we usually don’t have multiple labels on statements (Is that even legal in Swift?) and can optimize which loops need to be indexable.
> I really dislike the addition of magical builtin variables. Iterating through a FSA should just take the FSA down one dimension level, so
> let data = [2, 3; 1, 2, 3, 4, 8, 12]
> for x:[3;] in data
> total += x + x + x
> would be the pattern.
I’m assuming that automatic incomplete indexing would happen here, instead of a flat loop.
The point of the flat for-loop is to eliminate the drudgery of nesting per-dimension for-loops (and re-editing whenever a dimension value or the dimension count changes) and to let the implementation optimize traversal (especially if a processor vector type is used).
Mac, Internet, and Video Game Junkie
darylew AT mac DOT com
-------------- next part --------------
An HTML attachment was scrubbed...
More information about the swift-evolution