On Tuesday, January 02, 2018 10:37:17 Ali Çehreli via Digitalmars-d-learn wrote: > As soon as we call it "dynamic array", I can't help but think "adding > elements". Since GC is in the picture when that happens, it's essential > to think GC when adding an element is involved. > > Further, evident from your description it's a "slice" until you add > elements because the underlying memory e.g. can be a stack-allocated > fixed-length array. > > For these reasons, the interface that the program is using is a "slice". > Dynamic array is a different concept owned and implemented by the GC.
Except that from the standpoint of the API, T[] _is_ the dynamic array - just like std::vector is the dynamic array and not whatever its guts are - and the semantics are the same whether it's backed by the GC or by a static array or by malloc-ed memory or whatever. Appending works exactly the same. Reallocation works the same. None of that changes based on whether the dynamic array is backed by GC-allocated memory or not. It's just that the capacity is guaranteed to be 0 if it isn't GC-allocated and so the first append operation is guaranteed to reallocate. The semantics of T[] itself don't change regardless, and most code doesn't need to care one whit about what kind of memory backs the dynamic array. No matter what memory backed it to start with, you get the same appending semantics. You get the same semantics when accessing the data. You get the same semantics when passing the dynamic array around. None of that depends on what kind of memory the dynamic array is a slice of. T[] functions as a dynamic array regardless of what memory backed it to start with, and as such, I completely agree with the spec calling it the dynamic array. And as soon as you start talking about T[] not being a dynamic array, you get this weird situation where T[] has all of the operations and semantics of a dynamic array, but you're not calling it a dynamic array simply because it happens to be a slice of memory that wasn't GC-allocated. So, you have this type in the type system whose semantics don't care what memory currently backs it and where code will act on it identically whether it's GC-backed or not, but folks want to then act like it's something different and treat it differently just because it happens to not be GC-backed at the moment - and the same function could be called with both GC-backed and non-GC-backed dynamic arrays. The type and its semantics are the same regardless. Of course, understanding how and when reallocation occurs matters if you want to understand the exact semantics of copying a dynamic array around or when appending or reserve is going to result in a reallocation, but that doesn't necessitate calling the GC-managed buffer the dynamic array. It just requires understanding how it's the GC that manages capacity, reserve, and appending rather than the dynamic array itself. But the API is that of a dynamic array regardless. If it weren't, you couldn't append to T[] any more than you can append to an arbitrary range. As soon as you insist on calling them slices, you're basically talking about them as if they were simply ranges rather that than the container/range hybrid that they are. Regardless, the fact that they're a container/range hybrid is what makes this such a mess to understand. The semantics actually work fantastically if you understand them, but it sure makes understanding them annoyingly difficult. - Jonathan M Davis
