The demise of T[new]

Don nospam at nospam.com
Mon Oct 19 12:08:06 PDT 2009


Denis Koroskin wrote:
> On Mon, 19 Oct 2009 18:57:45 +0400, Leandro Lucarella <llucax at gmail.com> 
> wrote:
> 
>> Andrei Alexandrescu, el 18 de octubre a las 20:16 me escribiste:
>>> Here's what I wrote to Walter:
>>>
>>> ====================
>>> I'm going to suggest something terrible - let's get rid of T[new]. I
>>> know it's difficult to throw away work you've already done, but
>>> really things with T[new] start to look like a Pyrrhic victory. Here
>>> are some issues:
>>>
>>> * The abstraction doesn't seem to come off as crisp and clean as we
>>> both wanted;
>>>
>>> * There are efficiency issues, such as the two allocations that you
>>> valiantly tried to eliminate in a subset of cases;
>>>
>>> * Explaining two very similar but subtly different types to
>>> newcomers is excruciatingly difficult (I'll send you a draft of the
>>> chapter - it looks like a burn victim who didn't make it);
>>>
>>> * Furthermore, explaining people when to use one vs. the other is
>>> much more difficult than it seems. On the surface, it goes like
>>> this: "If you need to append stuff, use T[new]. If not, use T[]."
>>> Reality is much more subtle. For one thing, T[new] does not allow
>>> contraction from the left, whereas T[] does. That puts T[] at an
>>> advantage. So if you want to append stuff and also contract from the
>>> left, there's nothing our abstractions can help you with.
>>
>> I think this is getting overcomplicated. I don't see it as complex, I see
>> it like this:
>>
>> 2 types should be provided: array and slice.
>>
>> array is a *real* type, storing and owning memory, it should be something
>> like this (conceptually):
>>
>> class array(T)
>> {
>>     size_t length;
>>     size_t capacity;
>>     T[capacity] elements;
>> }
>>
>> 1) a pure reference type.
>> 2) 1 allocation only (interior pointers are not a problem, the GC have to
>>    support them anyways).
>> 3) easily appendable (capacity field).
>>
>> slice should be something like this:
>>
>> struct slice(T)
>> {
>>     size_t length;
>>     T* ptr;
>> }
>>
>> 1) a pure value type.
>> 2) no allocation at all, *ever*.
>> 3) not appendable at all.
>> 4) You can change both ptr and length, and you can mutate the elements 
>> (if
>>    not immutable).
>>
>> So a slice is a window to peek a chunk of data.
>>
>> Then you have the syntax. In this discussion, T[new] is array and T[] is
>> slice. I find that syntax very confusing. I think it could be even better
>> to just put those 2 types in object.d (well, do public imports of those
>> 2 types in object.d) and let the people write:
>>
>> array!T a;
>> slice!T s;
>>
>> The array literals should be immutable chunks of memory in the static
>> memory, as ClassInfo.init. The type of [1,2,3] should be, for example,
>> slice!(immutable int), so:
>> auto s = [1,2,3];
>> should create a slice!(immutable int) with length 3 and ptr pointing to
>> the static memory where the [1,2,3] was stored (this is what happens with
>> strings, right? So no surprises here, they are consistent).
>>
>> slice.dup should return an array. If you want to just copy the length and
>> ptr members, use assignment (it's a value type, remember)?
>>
>> auto s = [1,2,3];
>> auto t = s;
>> assert(s.length == t.length);
>> assert(s.ptr == t.ptr);
>> assert(&s != &t);
>>
>> Assignment of arrays is just a pointer assignment (is a reference type):
>>
>> auto a = [1,2,3].dup;
>> auto b = a;
>> assert(a is b);
>>
>> array.dup returns another array. array[] returns a slice though (you can
>> allow implicit casting from array to slice but I don't see the point as
>> array[] is short enough and more explicit). slices should not be
>> convertible to arrays (use slice.dup for that).
>>
>>
>> Back to the syntax, I think T[new] is *really* confusing. It tell me
>> nothing about the type, it provides the same information as calling it
>> it wazzzaaap!T for me. I *really* think it would be better to call it
>> array!T. But if we have both types, T[] is not clear anymore that is
>> a slice, again, you can't figure that out. So maybe T[] should be used 
>> for
>> arrays, not slices; if you want some syntax sugar I think T[] is more
>> guessable to be an array than a slice, and it would be a little more
>> backward compatible. Maybe slices can be T[..], but I'm not sure is clear
>> enough, again I think we could live with something more explicit like
>> array!T and slice!T. But at least slices should be part of the language,
>> because that should be the type of "array literals" (damn! that didn't
>> sound right =P).
>>
>>
>> I'm missing something? Why this shouldn't work?
>>
> 
> That's what was initially planned (except some nuances).
> 
> I also think we need a precedent of mapping built-in language type to a 
> library type, starting with Array!(T) and Range!(T). We could then map 
> V[K] to AArray!(K,V), T? to Nullable!(T) etc.
> 
> There is one big issue, though: classes and allocations via 'new' don't 
> work with CTFE. I believe this is something that is planned (Walter once 
> said that an entire subset of D called SafeD should work with CTFE), but 
> it is *very* hard to implement, not feasible in a nearest future for sure.

Don't worry. It's not hugely difficult to implement, though it'll be a 
while before all the bugs are ironed out. Most of the difficult stuff is 
already in place. (The CTFE memory bug is the difficult one).



More information about the Digitalmars-d mailing list