August 10, 2009
On Sun, Aug 9, 2009 at 4:29 PM, Walter Bright<newshound1@digitalmars.com> wrote:
> D has a number of subtle problems (performance and semantic) that arise when arrays are resized. The solution is to separate resizeable array types from slices. Slices will retain the old:
>
>   T[] slice;
>
> syntax. Resizeable arrays will be declared as:
>
>   T[new] array;
>
> The new expression:
>
>   new T[10]
>
> will return a T[new].
>
> T[new] will implicitly convert to T[], but not the other way.
>
> slice.length will become read-only.
>
> Under the hood, a T[new] will be a single pointer to a library defined type. This library defined type will likely contain three properties:
>
>    size_t length;
>    T* ptr;
>    size_t capacity;
>
> The usual array operations will work on T[new] as well as T[].
>
> Doing this change will:
>
> 1. fix many nasties at the edges of array semantics
>
> 2. make arrays implementable on .net
>
> 3. make clear in function signatures if the function can resize the array or not

This is a great change.  MiniD's array semantics are very similar to D's wrt. slicing, though I made the slight modification that array objects keep track of whether or not they are a slice of another array and behave slightly differently accordingly, and I've found it to be more intuitive.  I like that D is doing the same thing, and statically too ;)

The T[new] syntax isn't doing much for me, but then again, I don't have any better suggestions.
August 10, 2009
Lars T. Kyllingstad Wrote:

> Walter Bright wrote:
> > Lars T. Kyllingstad wrote:
> >> I've always wondered: Why are strings of type immutable(char)[], and not immutable(char[])?
> > 
> > So:
> > 
> >    string a = "hello";
> >    a = "foo";
> > 
> > works.
> 
> 
> Ah, of course. :) Thanks.
> 
> -Lars

The problem with immutable(char)[] was that any string can be resized, even slices.

Walter: what will the string types be aliased to now: still immutable(char)[] or immutable(char)[new]?

I think it would be best to have them use the array [new] type. Functions which do not modify the string length can mark the string as an in parameter, and immutable(char)[] should be castable to const(immutable(char)[new]) in such cases to still allow slices to be passed.
August 10, 2009
Jeremie Pelletier, el 10 de agosto a las 13:01 me escribiste:
> Lars T. Kyllingstad Wrote:
> 
> > Walter Bright wrote:
> > > Lars T. Kyllingstad wrote:
> > >> I've always wondered: Why are strings of type immutable(char)[], and not immutable(char[])?
> > > 
> > > So:
> > > 
> > >    string a = "hello";
> > >    a = "foo";
> > > 
> > > works.
> > 
> > 
> > Ah, of course. :) Thanks.
> > 
> > -Lars
> 
> The problem with immutable(char)[] was that any string can be resized, even slices.
> 
> Walter: what will the string types be aliased to now: still immutable(char)[] or immutable(char)[new]?

From: Walter Bright <newshound1@digitalmars.com>
Date: Mon, 10 Aug 2009 01:01:56 -0700
Subject: Re: T[new]
User-Agent: Thunderbird 2.0.0.22 (Windows/20090605)

Kagamin wrote:
>Of what type will strings be?

immutable(char)[]

>Of what type will be the result of concatenation?

T[new]

-- 
Leandro Lucarella (luca) | Blog colectivo: http://www.mazziblog.com.ar/blog/
----------------------------------------------------------------------------
GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145  104C 949E BFB6 5F5A 8D05)
----------------------------------------------------------------------------
El techo de mi cuarto lleno de galaxias
August 10, 2009
Jeremie Pelletier wrote:
<snip>
> Walter: what will the string types be aliased to now: still immutable(char)[] or immutable(char)[new]?
> 
> I think it would be best to have them use the array [new] type.

It would be more efficient to cut out this middleman for things that aren't going to change the length.  Which means most things that operate on the string type (and similarly wstring/dstring), since these types are designed to be immutable.  The change to T[] that's part of this plan would take it a stage further by making the length immutable as well.

> Functions which do not modify the string length can mark the string
> as an in parameter, and immutable(char)[] should be castable to
> const(immutable(char)[new]) in such cases to still allow slices to be
> passed.

The conversion would create an extra memory allocation.

Stewart.
August 10, 2009
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)[].

Stewart.
August 10, 2009
On Mon, 10 Aug 2009 14:38:24 -0400, Stewart Gordon <smjg_1998@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).

-Steve
August 10, 2009
Steven Schveighoffer wrote:
> On Mon, 10 Aug 2009 14:38:24 -0400, Stewart Gordon <smjg_1998@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.


Andrei
August 10, 2009
bearophile wrote:
> Walter Bright:
> 
> I like this general proposal, it sounds like something that can improve D a little. There are many other things that have to be improved in D, but baby steps are enough to go somewhere :-)
> 
>> Slices will retain the old:
>>     T[] slice;
>> syntax. Resizeable arrays will be declared as:
>>     T[new] array;
> 
> Such syntaxes have to be chosen wisely. I don't fully understand that syntax. And maybe I don't fully like it.
> I think the default (simpler) syntax has to be the most flexible and safer construct, that is resizable arrays. Slices can be seen as an optimization, so they can have a bit longer syntax.
> 

<snip>

Ya, not a nice syntax.
how about T[!static] ?! ;)

- --
My enormous talent is exceeded only by my outrageous laziness.
http://www.ssTk.co.uk
August 10, 2009
On Mon, 10 Aug 2009 15:21:48 -0400, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:

> Steven Schveighoffer wrote:
>> On Mon, 10 Aug 2009 14:38:24 -0400, Stewart Gordon <smjg_1998@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
August 10, 2009
Jeremie Pelletier wrote:
> Walter: what will the string types be aliased to now: still
> immutable(char)[] or immutable(char)[new]?

immutable(char)[]

> I think it would be best to have them use the array [new] type.

The vast majority of uses will not need to be resizeable.

> Functions which do not modify the string length can mark the string
> as an in parameter, and immutable(char)[] should be castable to
> const(immutable(char)[new]) in such cases to still allow slices to be
> passed.

A slice won't be castable to a resizeable.

1 2 3 4 5
Next ›   Last »