June 05, 2007
Derek Parnell wrote:
> On Mon, 04 Jun 2007 10:45:09 -0700, Walter Bright wrote:
> 
>>>>    T[n]   a;  // static array
>>>>    T[]    b;  // dynamic array
>>>>    T[new] c;  // resizeable array
>>> I'd propose a different nomenclature:
>>>
>>> T[n]   a;  // static array
>>> T[]    b;  // (array) slice
>>> T[new] c;  // dynamic array
>> I like "resizeable" array because it is pretty clear what it does.
> 
> I think you are quite wrong Walter. The new interpretation of 'x[]' is
> almost identical to what we used to think of as a slice. And the
> interpreatation of 'x[new]' is exactly what used to be known as a dynamic
> array. 
> 
> Your change will effect all code immediately whereas reversing the
> (changed) meaning of '[]' and '[new]' to mean 'resizable' and 'slice' will
> allow coders to change their coding over time. Unless of course that's what
> you are trying to do ...

Except that the non-resizable arrays will be more common in use than the fully dynamic ones. Thus, the resizable are a special case and deserve special syntax. *Except* that it's similar to const-by default, while D will use mutable-by default.

Long story short, IMHO, it makes more sense to do const-by-default everywhere, just as using non-resizable arrays by default. But what you're suggesting will probably be more consistent with the planned constness facilities. And as I understand it, their main selling point over const-by-default is the smaller number of changes required in existing code.


-- 
Tomasz Stachowiak
http://h3.team0xf.com/
h3/h3r3tic on #D freenode
June 05, 2007
Tom S wrote:
> Derek Parnell wrote:
>> On Mon, 04 Jun 2007 10:45:09 -0700, Walter Bright wrote:
>>
>>>>>    T[n]   a;  // static array
>>>>>    T[]    b;  // dynamic array
>>>>>    T[new] c;  // resizeable array
>>>> I'd propose a different nomenclature:
>>>>
>>>> T[n]   a;  // static array
>>>> T[]    b;  // (array) slice
>>>> T[new] c;  // dynamic array
>>> I like "resizeable" array because it is pretty clear what it does.
>>
>> I think you are quite wrong Walter. The new interpretation of 'x[]' is
>> almost identical to what we used to think of as a slice. And the
>> interpreatation of 'x[new]' is exactly what used to be known as a dynamic
>> array.
>> Your change will effect all code immediately whereas reversing the
>> (changed) meaning of '[]' and '[new]' to mean 'resizable' and 'slice' will
>> allow coders to change their coding over time. Unless of course that's what
>> you are trying to do ...
> 
> Except that the non-resizable arrays will be more common in use than the fully dynamic ones. Thus, the resizable are a special case and deserve special syntax. *Except* that it's similar to const-by default, while D will use mutable-by default.

I think it really depends.  I can imagine for a lot of folks it will basically boil down to parameter vs. local variable.  If it's a parameter you want slice-semantics, if it's a local variable you want resizeable semantics.  A quick grep through my code gave me about 400 lines where I used '~='.  That doesn't tell you all that much, but it does give something close to an upper bound.  For each of those lines a T[] somewhere is going to need to be changed to a T[new] (or whatever). The number could be less if I'm using auto.  But I also use
   T[] x; x.length = N;
a lot.  Those will need to be changed too.

On the other hand "[]" appears about 1700 times.  That says to me that arrays that I don't resize (whether in paramter or not) are probably significantly more common than those I do.  But either way it's a significant amount of code to change.

--bb
June 05, 2007
Walter Bright escribió:
> 
>    T[n]   a;  // static array
>    T[]    b;  // dynamic array
>    T[new] c;  // resizeable array
> 
>    a.length = 6;   // error, static array
>    b.length = 6;   // error, dynamic array is not resizeable
>    c.length = 6;   // ok
>    b = c;          // ok, implicit conversion of resizeable to dynamic
>    c = b;          // error
>    c = b[0..n];    // error
>    b = c[0..n];    // ok, but watch out if c is later resized
>    b = c[0..n].dup; // ok, no worries
>    c = cast(T[new])b; // ok, but this will be deliberate

I don't understand how dynamic arrays work with this change.

T[] b;        // b is a dynamic array of size... ???
b.length = 6; // error, dynamic array is not resizeable ????????

So maybe this should be:

T[] b = new T[6]; // ... of size 6, and 6 can
                  // be replaced with a dynamic variable

Is this the intention of it?

I've only wrote one program in D, and I used dynamic arrays as lists (AKA ArrayList in Java). So I guess my program will break with this change, because I can't concatenate anymore. Maybe I've been using dynamic arrays in the wrong way?
June 05, 2007
Ary Manzana wrote:
> Walter Bright escribió:
>>
>>    T[n]   a;  // static array
>>    T[]    b;  // dynamic array
>>    T[new] c;  // resizeable array
>>
>>    a.length = 6;   // error, static array
>>    b.length = 6;   // error, dynamic array is not resizeable
>>    c.length = 6;   // ok
>>    b = c;          // ok, implicit conversion of resizeable to dynamic
>>    c = b;          // error
>>    c = b[0..n];    // error
>>    b = c[0..n];    // ok, but watch out if c is later resized
>>    b = c[0..n].dup; // ok, no worries
>>    c = cast(T[new])b; // ok, but this will be deliberate
> 
> I don't understand how dynamic arrays work with this change.
> 
> T[] b;        // b is a dynamic array of size... ???
> b.length = 6; // error, dynamic array is not resizeable ????????
> 
> So maybe this should be:
> 
> T[] b = new T[6]; // ... of size 6, and 6 can
>                   // be replaced with a dynamic variable
> 
> Is this the intention of it?

Yep, I'm pretty sure that's what you'll have to do for a *non*-resizeable array.  On the other hand if you want to be able to resize (using Walter's not-so-popular syntax):

T[new] b;
b.length = 6;

> I've only wrote one program in D, and I used dynamic arrays as lists (AKA ArrayList in Java). So I guess my program will break with this change, because I can't concatenate anymore. Maybe I've been using dynamic arrays in the wrong way?  

Nope, the way you've been using them is fine.  But to get safer slices, something's got to change.  And since not resizing is less common than resizing, it makes more sense to change the syntax for the resizeable arrays.

--bb
June 05, 2007
Derek Parnell wrote:
> On Mon, 04 Jun 2007 10:45:09 -0700, Walter Bright wrote:
> 
>>>>    T[n]   a;  // static array
>>>>    T[]    b;  // dynamic array
>>>>    T[new] c;  // resizeable array
>>> I'd propose a different nomenclature:
>>>
>>> T[n]   a;  // static array
>>> T[]    b;  // (array) slice
>>> T[new] c;  // dynamic array
>> I like "resizeable" array because it is pretty clear what it does.
> 
> I think you are quite wrong Walter. The new interpretation of 'x[]' is
> almost identical to what we used to think of as a slice. And the
> interpreatation of 'x[new]' is exactly what used to be known as a dynamic
> array. 
> 
> Your change will effect all code immediately whereas reversing the
> (changed) meaning of '[]' and '[new]' to mean 'resizable' and 'slice' will
> allow coders to change their coding over time. Unless of course that's what
> you are trying to do ...
> 
> 

There's another issue. Function parameters cover most of the ground that this does, if not more. There's already a set of keywords that can be used here with the same meaning.

C++ has T const * as a single-allocate array and T* as the resizeable form (albeit only with realloc). It'd be a bit ugly, but D could do T const[] or T const([]) for the single-allocate array and T[] for the resizeable form.

T const[] also addresses the above issue of converting code. I'm working on a MUD currently, and since it's a text-based game just about everything involved is string catenation. Either I'd suddenly grow to love the auto keyword (but specifying types manually is a comforting sanity check), or I'd have to convert almost every string to be mutable.

Walter, you said already that you couldn't think of many cases where it would be useful to have an immutable array of mutable elements. But now it seems that not only are you implementing that, but you're making it the default. I'm confused. Why are you doing it?

I agree it's useful to have these slice arrays, but it's an edge case. Please don't require extra keywords to get to the common case.
June 05, 2007
It just occurred to me this morning that I may have missed something regarding the proposed const changes.  Given the following D 1.0 code, can someone tell me whether or how it will change in D 2.0?

    void alter( char[] str )
    {
        str[0] = 'x';
    }

    char[] buf = "abc".dup;

    alter( buf );
    alter( buf[1 .. $] );

    printf( "%.*s\n", buf ); // should print "xxc"



Sean
June 05, 2007
I believe that code would not need to change to retain existing behavior.

The function args aren't const by default since it's not using 'in'.  So it'll be fine.  The syntax used is also to pass a slice. which would become non-resizeable, which you're not resizing, so that's fine.  Slices are to retain their write through behavior, so that's fine.  Your initialization of buf would have an implicit cast from dup's T[new] to buf's T[], which works.  Passing a T[] to a function taking a T[] is perfectly normal..

So, that code 'just works'.

Later,
Brad

(now, time for Walter to point out the flaw in my reasoning)

On Tue, 5 Jun 2007, Sean Kelly wrote:

> Date: Tue, 05 Jun 2007 10:16:53 -0700
> From: Sean Kelly <sean@f4.ca>
> Reply-To: digitalmars.D.announce <digitalmars-d-announce@puremagic.com>
> To: digitalmars-d-announce@puremagic.com
> Newsgroups: digitalmars.D.announce
> Subject: Re: resizeable arrays: T[new]
> 
> It just occurred to me this morning that I may have missed something regarding the proposed const changes.  Given the following D 1.0 code, can someone tell me whether or how it will change in D 2.0?
> 
>     void alter( char[] str )
>     {
>         str[0] = 'x';
>     }
> 
>     char[] buf = "abc".dup;
> 
>     alter( buf );
>     alter( buf[1 .. $] );
> 
>     printf( "%.*s\n", buf ); // should print "xxc"
> 
> 
> 
> Sean
> 
June 05, 2007
Brad Roberts wrote:
> I believe that code would not need to change to retain existing behavior.
> 
> The function args aren't const by default since it's not using 'in'.  So it'll be fine.  The syntax used is also to pass a slice. which would become non-resizeable, which you're not resizing, so that's fine.  Slices are to retain their write through behavior, so that's fine.  Your initialization of buf would have an implicit cast from dup's T[new] to buf's T[], which works.  Passing a T[] to a function taking a T[] is perfectly normal.. 
> 
> So, that code 'just works'.

Thanks for clearing this up.  After thinking about the talk yesterday I'd started to wonder if the "write through" feature of slices might change, etc.  It's very reassuring to know that this isn't the case.


Sean
June 05, 2007
Sean Kelly wrote:
> Walter Bright wrote:
>> Sean Kelly wrote:
>>>
>>> Well, I think it is very rare for a function to want to resize an array that isn't passed by reference.  My first reaction would be to disallow resizing of non-ref array parameters entirely.  Since resizing may occur in place, this could be seen as a mutating operation on the underlying data.  If the user wants to resize a non-ref array parameter for local use he use assign ops and such.
>>
>> That was my first reaction too, but Frits posted a reasonable use case.
> 
> Do you mean:
> 
>     T[] foo(<parameters>, T[] buffer = null) {
>         buffer.length = <something>;
>         <fill buffer>
>         return buffer;
>     }
> 
> Wouldn't it work if changed to this:
> 
>     T[] foo(<parameters>, T[] buffer = null) {
>         if( buffer.length < newSize )
>             buffer = new T[newSize];
>         <fill buffer>
>         return buffer;
>     }
> 
> I think it's arguable that the second form is also more meaningful given that the array is not passed by reference.

Given the above, am I correct in assuming that it will only be illegal to resize an array via .length if the underlying data is const?  If the data is not const then it seems completely legitimate to resize the supplied array, even if doing so means an in-place expansion.


Sean
June 07, 2007
Sean Kelly wrote:
> Given the above, am I correct in assuming that it will only be illegal to resize an array via .length if the underlying data is const?  If the data is not const then it seems completely legitimate to resize the supplied array, even if doing so means an in-place expansion.

Making the referred to data const does not inhibit resizing, because resizing does not change the referred to data.

The key to understanding dynamic arrays is understanding their representation. Dynamic arrays of const data are like a C++ struct defined as:

struct DynamicArray
{
	size_t length;
	const char *ptr;
}

Here, I can change .length and .ptr EVEN THOUGH the data being pointed to is const.