T[new]

Steven Schveighoffer schveiguy at yahoo.com
Mon Aug 10 12:38:40 PDT 2009


On Mon, 10 Aug 2009 15:21:48 -0400, Andrei Alexandrescu  
<SeeWebsiteForEmail at erdani.org> wrote:

> Steven Schveighoffer wrote:
>> On Mon, 10 Aug 2009 14:38:24 -0400, Stewart Gordon  
>> <smjg_1998 at yahoo.com> wrote:
>>
>>> Since nobody's yet asked....
>>>
>>> What type would .dup and .idup return?
>>>
>>> The best choice I can see is to make .dup return T[new] and .idup  
>>> return invariant(T)[].
>>  This brings up another question.  Should something like  
>> immutable(T)[new] or const(T)[new] be even valid?  Consider this:
>>  immutable(char)[new] str = "hello".idup; // not sure how you convert a  
>> literal to an array, but assume it works for now.
>>  assert(str.capacity == 16); // assume GC still allocates 16 minimum  
>> blocks
>> str ~= " there";
>>  auto slice = str[5..$];
>>  str.length = 5;
>>  str ~= " world";
>>  assert(slice == " there"); // fails?
>>  We most likely have the same issue here with immutable data as we do  
>> today, just not as obvious.  Although it's a corner case, it does  
>> violate immutability without casts.
>>  There are several options:
>>  1. immutable(T)[new] and const(T)[new] are invalid.  This limits us  
>> more than the current regime, but is a questionable construct to begin  
>> with, considering it allows appending in place (you can always create a  
>> new array with concatenation).
>> 2. immutable(T)[new] and const(T)[new] are equivalent to  
>> immutable(T[new]) and const(T[new]) respectively.  This simplifies  
>> generic programming and still prevents abuses.
>> 3. when you shrink an array of immutable/const elements' length, the  
>> capacity automatically shrinks to prevent overwriting previous data.   
>> This still leaves mutable data with the overwrite problem, but it  
>> doesn't violate const.
>> 4. same as #3 but do it for both immutable or mutable arrays.
>>  Also, implicit casting to const needs to be addressed, normally you  
>> can't do this with templated types (if that's how the underlying type  
>> is implemented).
>
> I think 1 is a good option. Essentially you can't have a resizeable  
> array of immutable data. Functional languages don't have such a thing.  
> If we go for (3), code that looks tighter is in fact more wasteful as  
> every shrinking+expanding cycle causes a new allocation and a copy.

Consider this then:

template ArrayOf(T)
{
   alias T[new] ArrayOf;
}

Is ArrayOf!invariant(char) valid?  Should it be?  I'm not sure, this was  
my focus of option 2.

-Steve



More information about the Digitalmars-d mailing list