== Quote from Andrei Alexandrescu (seewebsiteforem...@erdani.org)'s article > > 3. A T[new] should be implicitly convertible to a slice. For example: > > > > auto foo = someFunctionThatReturnsTnew(); > > // foo is a T[new]. > > T[] bar = someFunctionThatReturnsTnew(); > > // Works. bar is a T[]. The T[new] went into oblivion. > > > > This solves the problem of slices not being closed over .dup and ~. > Check.
So then why is slices not being closed over .dup, ~, etc. still a problem? With implicit conversion, they for all practical purposes are. > > 4. It should be guaranteed that no block of memory is ever referenced by > > more > > than one T[new] instance. This is needed to guarantee safety when > > appending to > > immutable arrays, etc. > That doesn't go with reference semantics. Uncheck. > > 5. Assigning a T[new] to another T[new] should be by reference, just like > > assigning a class instance to another class instance. > Check. (BTW contradicts 4) There was a slight misunderstanding here. When I say an instance, I mean one T[new] heap object == one instance, no matter how many pointers/references to this instance you have. The assumption is that T[new] objects live entirely on the heap and have semantics similar to classes. For example: uint[new] foo = new uint[100]; uint[new] bar = foo; // Really just a pointer assignment. Now, both foo and bar point to the same uint[new] instance. If anything is modified via foo, it is seen when viewed from bar and vice-versa. To clarify, no *main block of memory that holds the data in the array* is ever referenced by more than one T[new] *heap object*. > > Assigning a T[] to a T[new] > > should duplicate the memory block referenced by the T[] because this is > > probably > > the only way to guarantee (4). > No check, but could have been done. Actually, this can even be done by COW. Initially, assigning a T[] to a T[new] could just be a pointer assignment and setting a flag, as long as a copy of the data is made when you try to increase the length of the T[new] or append to it. Basically, as long as you use the T[new] as if it were a T[], no copying needs to be done. > > 6. Since T[new] guarantees unique access to a memory block, it should have > > an > > assumeUnique() method that returns an immutable slice and sets the T[new]'s > > reference to the memory block to null. This solves the problem of building > > immutable arrays without the performance penalty of not being able to > > pre-allocate > > or the unsafeness of having to cowboy cast it to immutable. > Uncheck. Now that I've explained my uniqueness thing better, does this sound feasible? > > 7. As long as the GC is conservative, there absolutely *must* be a method > > of > > manually freeing the memory block referenced by a T[new] provided that the > > GC > > supports this operation, though it doesn't have to be particularly pretty. > > In > > general, since D is a systems language, T[new] should not be too opaque. A > > good > > way to do this might be to make all of the fields of the T[new] public but > > undocumented. If you *really* want to mess with it, you'll read the source > > code > > and figure it out. > Check while delete still exists. Please use malloc for that stuff. As long as I can get at the pointer to the memory block held by T[new] I can pass it to GC.free. All that would really be needed is a .ptr property that does something like what .ptr does for T[]s. > So now: every place I've said "check" means there was implementation and > book-quality illustrated documentation that Walter and I have done with > the sweat of our brow. At the end we looked at the result and concluded > we should throw away all that work. > Andrei This begs the question: Why? Walter's post on the subject was rather brief and I can't understand for the life of me why you guys would throw away such an elegant solution. Given that we already agree that a T[new] can be implicitly cast to a T[], the lack of closure under ~, .dup, etc. seems like a non-issue. When I was a beginner, before I got into templates, a major attraction to D was that it was a fast, compiled language where basic things like arrays (mostly) just worked. To take away all the syntactic sugar for appending and lengthening from arrays and push this into a separate library type that doesn't feel like a first class object or (I assume) even support most array semantics would be a massive, massive kludge no matter how well-implemented that library type was.