www.digitalmars.com         C & C++   DMDScript  

digitalmars.dip.ideas - Separate slices and dynamic arrays

reply monkyyy <crazymonkyyy gmail.com> writes:
```d
int[3] foo;
int[] bar=foo[];
bar[1]=3;
assert(foo[1]==3);//works, bar is a reference to foo
bar~=5;//oh no
bar[2]=4;
assert(foo[2]==4);//failure, bar stopped being a reference to foo
```

slices are sometimes better pointer math or sometimes gc'ed 
managed memory. This is unsafe and lacks clear ownership.

So two parts:

Introduce `int[?]` as a dynamic array, it "owns" the memory and 
duplicates on assignment from slices.

Deprecate append to slices.

`auto bar=foo[];` would still be a slice
Jul 31
parent reply Quirin Schroll <qs.il.paperinik gmail.com> writes:
On Wednesday, 31 July 2024 at 23:07:14 UTC, monkyyy wrote:
 ```d
 int[3] foo;
 int[] bar=foo[];
 bar[1]=3;
 assert(foo[1]==3);//works, bar is a reference to foo
 bar~=5;//oh no
 bar[2]=4;
 assert(foo[2]==4);//failure, bar stopped being a reference to 
 foo
 ```

 slices are sometimes better pointer math or sometimes gc'ed 
 managed memory. This is unsafe and lacks clear ownership.

 So two parts:

 Introduce `int[?]` as a dynamic array, it "owns" the memory and 
 duplicates on assignment from slices.

 Deprecate append to slices.

 `auto bar=foo[];` would still be a slice
I think your confusion is somewhat warranted by the fact that many people on the forum call slices dynamic arrays. I don't. I'm careful with technical terms because they inform people's intuition about things, and in my intuition, dynamic arrays don't overlap. D does have dynamic arrays, though: Array literals and `new int[](n)` is what I would call dynamic arrays. But they evaluate to only a slice of that dynamic array. Slices never own data. If you append to a slice, it may have enough capacity and is being extended in-place. If you concatenate two of them or append one that doesn't have enough capacity, a new dynamic array is allocated, stuff is copied to it, and you get a slice of that data. If you append, you can only write to the lower insides of the result if you don't care if it possibly affects some other slice. And sometimes, you actually do not care, especially if the underlying type isn't even mutable, like with strings. With mutable elements, you might get some “spooky action at a distance” vibes, but then you're using slices incorrectly. You can always force a copy with `dup`. You can't force an in-place extension if there's just not enough capacity. If you want an owning dynamic array type, you can make your own type. Probably. Because I don't really know what you mean by owning the data. You probably don't mean it in the “responsible for freeing” sense, and I don't know any other sense. The only thing I can imagine you'd want to have owned is in a vector-like type that one can append to, and which, contrary to built-in slices, on exceeding capacity, does not copy the elements to the newly allocated bigger buffer, but moves them. It'd be similar to how iterators of a C++ vector are invalidated if you append to it. Walter once proposed deprecating slice append and slice length assignment, and he faced almost unanimous backash. Slice append is very, very useful in small programs and at CTFE. Even Zig acknowledges how useful such array manipulation is and allows them at compile-time (not at run-time though, as it's not a GC language). D's slices are what in C++ is a vector or string, a span or string_view, or a valarray, or even something like an output iteratior. My first instinct was: This is either nuts or sublime genius, and it's most definitely the latter. I work with C++. It's my professional job. In our codebase, we don't use the stdlib's string view because that thing can be initialized with string temporaries and if you pass a temporary string to a function takes a string view (for which there is no indication whatsoever) and that function stores that somewhere, you got yourself a dangling pointer stored. Our in-house string view requires explicit construction from an rvalue string, so there is an indication that we risk a dangling pointer. Why am I saying this? In D, that's a non-issue. If you pass a slice to a function and that function decides to store it, fine. The GC keeps the memory around as needed. In C++, I must decide whether to take as argument or store a sting or a string view. The latter is dirt cheap and quick, but it doesn't (co-)own the memory. Please, don't force this kind of decision onto D. It's simply great not to have to choose.
Aug 02
parent monkyyy <crazymonkyyy gmail.com> writes:
On Friday, 2 August 2024 at 21:43:33 UTC, Quirin Schroll wrote:
 I think your confusion is somewhat warranted
Im not confused. I just value what the compiler does over the spec and over peoples words: Its trivial to write example code for either world view that works flawlessly, with a footgun where they overlap; therefore d has both world views. This should be low priority, but above the safe discussions that is currently gripping the zeitgeist.
 Walter once proposed deprecating slice append and slice length 
 assignment, and he faced almost unanimous backash.
as he should; unlike this suggestion that would be removing features completely I wouldnt deprecate slice append until a separate built in data structure picks up the functionality
 D's slices are what in C++ is a vector or string, a span or 
 string_view, or a valarray, or even something like an output 
 iteratior. My first instinct was: This is either nuts or 
 sublime genius, and it's most definitely the latter.
c++ is overengineered and verbose, d sometimes isnt; it is 95% correct as is, idk the compiler details but Id copy and paste the code and make minor edits if it was my datastructure with such a problem
  In D, that's a non-issue. If you pass a slice to a function 
 and that function decides to store it, fine. The GC keeps the 
 memory around as needed.
~~I dont actaully think its unsafe or care about safety; everyone else's world view does however~~
Aug 02