> On Aug 2, 2017, at 11:44 AM, Félix Cloutier via swift-evolution > <swift-evolution@swift.org> wrote: > > >> Le 31 juil. 2017 à 18:54, Xiaodi Wu <xiaodi...@gmail.com >> <mailto:xiaodi...@gmail.com>> a écrit : >> It doesn't allow you to specify the size of the array, it's just a promise >> that the array is some immutable size. For instance, a `fixed [CGFloat]` >> would be a terrible type to represent a vector, but a >> FixedSizeArray<CGFloat, 4> would be appropriate, at least for the backing >> storage. A raw tuple would be a poor choice because dynamically indexing >> into them is painful. >> >> Shouldn't this be solved by improvements to tuples? It's a highly desired >> feature (by me and at least a few others) to allow tuples to conform to >> protocols, whether fixed-size arrays are added or not. I expect that >> conforming homogeneous tuples to Collection and enabling subscripting is >> simply a matter of time. > > Of course, if this happens, the point is moot and we have the type of > fixed-size arrays that I've been asking for. However, crystal-balling Chris's > last comment on the matter, it looks like it might not be happening too soon > <https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170724/038225.html>. > >> `fixed` is only useful when the compiler can determine the size of the array >> statically. This makes it mostly useless as a storage qualifier if you >> received the array as a parameter (*even* if you received a `fixed` array), >> because you know that it has a constant size but you don't know what that >> size is. >> Therefore, using a fixed-size array as a generic parameter (crucially, such >> as `fixed [fixed [Int]]`) is unlikely to work. >> Even if that semantic hurdle is overcome, we'd still have no idea how much >> memory to allocate for the outer array's buffer to make it work. >> >> As John McCall has replied, the array's bounds don't need to be statically >> known for fixed-size arrays to have benefits. > > This (partially) applies to the first point, but it leaves a lot of holes. > The size does not need to be statically known, but you need to know how much > memory you're going to need ahead of allocating it. How much memory do you > need for this? > >> var foo = fixed [Int]() >> for i in 0..<param { >> foo.append(i) >> } > > Arrays can't work if elements don't have a fixed size. How big is an element > in this example?
This is not the idea. The idea is more like let n = ... var foo = [Int x n](repeating: 13) The bound value is still fundamentally part of the type of the variable; it's just that the actual value is not known statically. John. >> var foo = fixed [fixed [Int]]() >> foo.append([1]) >> foo.append([2, 3]) > > > Where do you allocate this array's storage, and how big is it? > >> struct Foo { >> var array: fixed [Int] >> } >> >> var foo = Foo() >> foo.array.append(4) > > > In the general case, this makes `fixed` meaningful as a type annotation for > parameters, but instantiating such an object in the first place would require > you to give up a lot of flexibility in how it's populated. The unconstrained > problem of finding how many elements you'll have in an array is uncomputable. > > You could say that a fixed-size array stays as big as it was when it was > instantiated, but this still causes problems with fixed-size arrays in > structures (storage has already been allocated when the initializer runs), > and with generic collections (you couldn't initialize a variable-sized array > of fixed-size arrays, for instance). >> Even if `fixed [fixed [Int]]` could work, then each inner array could still >> have a different size, which is almost certainly not what you intend by >> nesting two fixed-size arrays. >> >> That's fair, but why at that point wouldn't you make your own Matrix type of >> fixed size, which uses an Array of fixed size as the underlying storage? > > I'd do it if I needed to, but there are plenty of 2D arrays that are just > that and don't need their own wrapper type to function, and I'd be happier to > not do it. >> Layout compatibility is important if you want to use fixed-size arrays to >> replace the clunky tuples that currently represent fixed-size arrays in >> structs exported from C (which is probably my one single biggest motivation >> for fixed-size arrays). You can't achieve layout compatibility if the size >> is part of the data instead of part of the type. >> >> For me, that's an anti-goal, as IMO tuples are the most sensible way of >> bridging a lot of these fixed-size arrays from C. Quite simply, I'd argue >> that the most idiomatic way to represent four CGFloat instances is >> `(CGFloat, CGFloat, CGFloat, CGFloat)`. The solution to certain operations >> being clunky with tuples is to improve the ergonomics of tuples. For >> instance, if we need a shorthand to avoid typing all those `CGFloat`s, then >> add one: `(4 * CGFloat)`. If we need subscripting, then add it. > > I think that any template-based fixed-size array structure would still need > that kind of (4 * CGFloat) syntax to be implemented, or some other facility > to allocate a parameterized amount of automatic storage. With that said, if > we can implement fixed-size arrays with just that without having to wait for > the restrictions on anonymous types to be lifted, to me, it's a fully > acceptable solution. > >> Besides, attaching fixed-size array semantics to an inherently variable-size >> Array is awkward. For `fixed` to be effective, it needs to disable methods >> that change the size of the array, or warn that you're using them. I don't >> like the cross-concern impact: now a keyword needs to know about method >> implementations to restrict them. It also has to work with extension methods >> on the Array type, and it shouldn't apply to just mutating functions because >> mutations that don't change the length of the array are fine. >> >> The idea is that all facilities which would benefit from knowing that an >> array is of a fixed count would opt into that benefit by indicating as such. >> That is, all stdlib array methods that are guaranteed to preserve the size >> of the array would be annotated as such. Again, by analogy to the ownership >> manifesto's design where functions that take shared arguments could be >> optimized on the basis of such annotation. The rest would fall out naturally. > > There are more problems to this that you may be able to iron out but that > make the story more complex still. How do you annotate > MutableCollection-based algorithms, or any other protocol-based extension > that doesn't directly accept an array? What's the syntax of an Array > extension method, which doesn't have an explicit self parameter, to mean that > the function is mutating but doesn't change the array's bounds? > > > _______________________________________________ > 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