June 07, 2007
Walter Bright wrote:
> 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.

Okay, that makes sense.  So I'm not sure I entirely understand the problem with resizing even mutable array in place.  Could this just be an instance where documentation is indeed sufficient?  I can't think of a situation where I would actually pass a slice of a buffer to a routine that may grow that buffer when writing to it--it just doesn't make any sense from a use perspective.  Is this something that we really need to add const features to check?


Sean
June 07, 2007
Sean Kelly wrote:
 > Okay, that makes sense.  So I'm not sure I entirely understand the
> problem with resizing even mutable array in place.  Could this just be an instance where documentation is indeed sufficient?  I can't think of a situation where I would actually pass a slice of a buffer to a routine that may grow that buffer when writing to it--it just doesn't make any sense from a use perspective.  Is this something that we really need to add const features to check?

I don't know if this helps, but currently the following code behaves unexpectedly with version=bad

> import std.stdio;
> 
> void main()
> {
>     char[] data = "1 50.0 60".dup;
> 
>     writefln( data[0..1].withDecimals() );
>     writefln( data );                      // with version=bad prints "1.00.0 60" instead of "1 50.0 60"
>     writefln( data[2..6].withDecimals() );
>     writefln( data[7..$].withDecimals() );
> }
> 
> char[] withDecimals(char[] num)
> {
>     foreach (i, c; num)
>         if (c == '.')
>             return num;
> 
> version(bad)
> {
>     num ~= ".0";
>     return num;
> }
> else
> {
>     return (num ~ ".0");
> }
> 
> }      

I'm not sure what the suggested rewrite of this would be. To avoid unnecessary dup'ing, perhaps:

> 
> private char[new] withDecimals(char[new] num, bool needsDup)
> {
>     foreach (i, c; num)
>         if (c == '.')
>             return num;
> 
>     if (needsDup)
>         num = num.dup;
>     num ~= ".0";
>     return num;
> }
> 
> char[new] withDecimals(char[new] num)
> {
>     return withDecimals(num, false);
> }
> 
> char[] withDecimals(char[] num)
> {
>     return withDecimals(cast(char[new])num, true)
> }
>  

   -- Reiner
June 07, 2007
Reiner Pope wrote:
> I'm not sure what the suggested rewrite of this would be. 
Actually, it would make more sense to template it:

> char[new=IsNew] withDecimals(bool IsNew)(char[new=IsNew] num)
> {
>     foreach (i, c; num)
>         if (c == '.')
>             return num;
> 
>     char[new] newNum;
>     static if (IsNew)
>         newNum = num;
>     else
>         newNum = num.dup;
> 
>     newNum ~= ".0";
>     return newNum;
> }


  -- Reiner
June 07, 2007
Walter Bright skrev:

> [...] the difference between static arrays and dynamic arrays is very large. For one thing, static arrays are passed by value, and dynamic arrays by reference.

This sounds intriguing. Does this mean that static arrays will be passed by value in D 2.0? Will string literals become dynamic (invariant) arrays instead of static too?

/Oskar
June 08, 2007
Oskar Linde wrote:
> Walter Bright skrev:
> 
>> [...] the difference between static arrays and dynamic arrays is very large. For one thing, static arrays are passed by value, and dynamic arrays by reference.
> 
> This sounds intriguing. Does this mean that static arrays will be passed by value in D 2.0?

Yes.

> Will string literals become dynamic (invariant) arrays instead of static too?

They'll be invariant static arrays.
June 08, 2007
Walter Bright skrev:
> Oskar Linde wrote:
>> Walter Bright skrev:
>>
>>> [...] the difference between static arrays and dynamic arrays is very large. For one thing, static arrays are passed by value, and dynamic arrays by reference.
>>
>> This sounds intriguing. Does this mean that static arrays will be passed by value in D 2.0?
> 
> Yes.

That is wonderful! Another wrinkle ironed out.

>> Will string literals become dynamic (invariant) arrays instead of static too?
> 
> They'll be invariant static arrays.

Yeah, I got that a few minutes after posting from another post.  My only (minor) concern here was the potential performance penalty of passing string literals to simple template functions, like

void foo(T)(T x) {...},

but there are plenty of ways to deal with that. For example, since they are invariant, I guess they could be passed by reference behind the scenes anyway.

/Oskar
June 08, 2007
"Walter Bright" <newshound1@digitalmars.com> wrote in message news:f4b70o$i3t$1@digitalmars.com...
> Oskar Linde wrote:
>
> They'll be invariant static arrays.

Why wouldn't they be invariant unresizable arrays?  Or do you plan on fixing all the special casing stuff that has to be taken into account when using string literals in {templates, array literals, AA literals, etc.}?


June 08, 2007
Jarrett Billingsley wrote:
> "Walter Bright" <newshound1@digitalmars.com> wrote in message news:f4b70o$i3t$1@digitalmars.com...
>> Oskar Linde wrote:
>>
>> They'll be invariant static arrays.
> 
> Why wouldn't they be invariant unresizable arrays?

Because static arrays can be implicitly cast to unresizable arrays, but not vice versa.

> Or do you plan on fixing all the special casing stuff that has to be taken into account when using string literals in {templates, array literals, AA literals, etc.}? 

I don't know what you mean.
June 08, 2007
"Walter Bright" <newshound1@digitalmars.com> wrote in message >
> Because static arrays can be implicitly cast to unresizable arrays, but not vice versa.

Why would you need it to implicitly cast to a static array?  So you can initialize things like "char[4] = "abcd";" ?

>
> I don't know what you mean.

// cannot implicitly convert expression (["hi","bye"]) of type char[][2] to
char
// auto a = ["hi", "bye"];

// works
auto a = ["hi"[], "bye"];

int[char[]] aa;

// cannot implicitly convert expression ("bye") of type char[3] to char[2]
//aa = ["hi":1, "bye":2];

// works
aa = ["hi"[]:1, "bye":2];

typeof(T[0]) foo(T...)()
{
    return T[0];
}

// Error: functions cannot return static array char[2]
//foo!("hi")();

// works
foo!("hi"[])();

Templates also have to deal with static array types in completely different ways, since they can't be returned and their .init is not the same type as them.


June 09, 2007
Walter Bright wrote:
> Sean Kelly wrote:
>> Walter Bright wrote:
>>> (The problem is if I pass a slice to a function, and then that function reallocates the slice by changing the length or appending to it, it can affect other slices into the same data in very hard-to-explain ways.
>>
>> I'm not sure I understand how a reallocation could affect other slices into the same data.  If a reallocation occurs, that reallocation will be into entirely new memory, provided the slice doesn't start at the head of a memory block.  Is it the condition I just mentioned that's a problem?  If so, I suppose it is one way to trick the compiler into thinking the reference no longer refers to const data, when in fact it does.  If not, could you point me in the right direction?
> 
> Given:
> 
>     int[] a = new int[7];
>     int[] b = a[1..6];
>     b[1] = 2;   // writes through to a[2]
>     b.length = 4;
>     b[1] = 3;   // writes through to a[2]
>     b.length = 6;
>     b[1] = 4;   // does not write through to a[2]
> 

So, is that the problem we are trying to solve? Why not just simply make it so that setting .length *allways* creates a new array?

Hum, now that I think about it, this may not only be a better solution, it may be the *only* real solution. Even, with the new resizable/unresizable array proposal you can have the same problem as above:

  int[new] a = new int[7];
  int[new] b = a;
  b.length = 6;

  b[1] = 2;   // writes through to a[1]
  b.length = 4;
  b[1] = 3;   // writes through to a[1]
  b.length = 10;
  b[1] = 4;   // does not write through to a[1]

Why does this problem exist? Because, setting an array length may or may not create a new array, and there isn't a way to know which will happen.  Well, in that code segment we can see when it will resize, but we can't know in the general case (like when we receive an array as a function parameter). This makes setting .length as very unsafe operation, if not plain *broken*.

(Oskar, I would particularly like to hear your opinion on this)

-- 
Bruno Medeiros - MSc in CS/E student
http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D