Thread overview
initializedArray
Dec 20, 2011
Andrej Mitrovic
Dec 20, 2011
Paul D. Anderson
Dec 20, 2011
Dejan Lekic
Dec 20, 2011
Andrej Mitrovic
Dec 20, 2011
Andrej Mitrovic
Dec 20, 2011
Philippe Sigaud
Dec 20, 2011
Andrej Mitrovic
Dec 21, 2011
Philippe Sigaud
Dec 21, 2011
Andrej Mitrovic
Dec 21, 2011
Andrej Mitrovic
December 20, 2011
I think it would be cool to have an initializedArray function, which creates and initializes an array with a *specific* initializer. A hardcoded example would be:

import std.array;

auto initializedArray(F:float[])(size_t size, float init)
{
    auto arr = uninitializedArray!(float[])(size);
    arr[] = init;
    return arr;
}

void main()
{
    float[] arr = initializedArray!(float[])(3, 0.0f);
    assert(arr[] == [0.0f, 0.0f, 0.0f]);
}

Currently there's no D syntax for using new on arrays and specifying a specific initializer, so maybe we should have this as a library function. Thoughts?
December 20, 2011
I think this is a great idea and a good example of adding to the library rather than changing the syntax.

Paul

"Wouldn't the sentence 'I want to put a hyphen between the words Fish and And and And and Chips in my Fish-And-Chips sign' have been clearer if quotation marks had been placed before Fish, and between Fish and and, and and and And, and And and and, and and and And, and And and and, and and and Chips, as well as after Chips?" — Martin Gardner

On Tuesday, 20 December 2011 at 12:55:18 UTC, Andrej Mitrovic wrote:
> I think it would be cool to have an initializedArray function, which
> creates and initializes an array with a *specific* initializer. A
> hardcoded example would be:
>
> import std.array;
>
> auto initializedArray(F:float[])(size_t size, float init)
> {
>   auto arr = uninitializedArray!(float[])(size);
>   arr[] = init;
>   return arr;
> }
>
> void main()
> {
>   float[] arr = initializedArray!(float[])(3, 0.0f);
>   assert(arr[] == [0.0f, 0.0f, 0.0f]);
> }
>
> Currently there's no D syntax for using new on arrays and specifying a
> specific initializer, so maybe we should have this as a library
> function. Thoughts?


December 20, 2011
I would go even further, and give a *function* as an argument - function that will be used to initialise values.

December 20, 2011
On 12/20/11, Dejan Lekic <dejan.lekic@gmail.com> wrote:
> I would go even further, and give a *function* as an argument - function that will be used to initialise values.

Well I don't know about functions yet, but I did need to use another array as an initializer. So the new implementation takes care of that via lockstep:

http://www.ideone.com/gKFTK
December 20, 2011
*Also those two templates can be merged, I just have to change the constraints.
December 20, 2011
On Tue, Dec 20, 2011 at 21:20, Andrej Mitrovic <andrej.mitrovich@gmail.com> wrote:
> On 12/20/11, Dejan Lekic <dejan.lekic@gmail.com> wrote:
>> I would go even further, and give a *function* as an argument - function that will be used to initialise values.
>
> Well I don't know about functions yet, but I did need to use another array as an initializer. So the new implementation takes care of that via lockstep:

from : http://www.ideone.com/gKFTK :

unittest
{
    auto arr2 = initializedArray!(int[][])([[1, 2], [3, 4]], 2, 2);
    assert(arr2 == [[1, 2], [3, 4]]);
}

1) What's the difference with using auto arr2 == [[1,2],[3,4]].dup;  ?
(I honestly asks, I don't know much about D's assignements)

2) You can get the lengths of [[1,2],[3,4]], so the 2,2 args is redundant. What happens if you type:

auto arr2 = initializedArray!(int[][])([[1, 2], [3, 4]], 4, 10);

3) I still think you should relax the constraint on the init value's type. You do not need it to be *exactly* BaseElementType!T. Thats stops you from writing

auto arr2 = initializedArray!(float[][])(3,  2,3);

4-ish) No need to attribute the rank/BaseElementType code to me :-)
December 20, 2011
On 12/20/11, Philippe Sigaud <philippe.sigaud@gmail.com> wrote:
> 1) What's the difference with using auto arr2 == [[1,2],[3,4]].dup;  ?
> (I honestly asks, I don't know much about D's assignements)

dup is not a deep copy, it only copies the first elements. The first elements are two slices, so:

void main()
{
    auto a = [[1, 2], [3, 4]];
    auto b = a.dup;

    a[0][0] = 10;
    assert(b[] == [[1, 2], [3, 4]]);  // fails, b[0][0] is 10
}


> 2) You can get the lengths of [[1,2],[3,4]], so the 2,2 args is redundant. What happens if you type:
>
> auto arr2 = initializedArray!(int[][])([[1, 2], [3, 4]], 4, 10);

Right, it's broken to say the least. That's what I get for a 10 second implementation.. Btw, uninitializedArray takes variadic arguments, how would I get the lengths of the dimensions as a tuple that can be passed in place of the variadic argument? I.e.:

auto dupArray(int[][] src)  // say src is int[1][2]
{
    auto arr = uninitializedArray!(int[][])( /* need 1, 2 here */ );

    // ..then copy each element..
}

I could use a mixin, but there should be an easier way to do this? You're good with templates so I'm asking you! :)

> 3) I still think you should relax the constraint on the init value's type. You do not need it to be *exactly* BaseElementType!T. Thats stops you from writing
>
> auto arr2 = initializedArray!(float[][])(3,  2,3);

I often fall to this trap. I think there's a syntax for checking if a type is implicitly convertible to another type? I haven't read your book fully yet, btw.

> 4-ish) No need to attribute the rank/BaseElementType code to me :-)
>

I say the same thing for when people use my code, but usually it's best not to assume ownership. :)
December 21, 2011
On Tue, Dec 20, 2011 at 23:42, Andrej Mitrovic <andrej.mitrovich@gmail.com> wrote:
> On 12/20/11, Philippe Sigaud <philippe.sigaud@gmail.com> wrote:
>> 1) What's the difference with using auto arr2 == [[1,2],[3,4]].dup;  ?
>> (I honestly asks, I don't know much about D's assignements)
>
> dup is not a deep copy, it only copies the first elements. The first elements are two slices

Ah OK. Where as your version does a deep dupping, I see.

>> 2) You can get the lengths of [[1,2],[3,4]], so the 2,2 args is redundant. What happens if you type:
>>
>> auto arr2 = initializedArray!(int[][])([[1, 2], [3, 4]], 4, 10);
>
> Right, it's broken to say the least. That's what I get for a 10 second implementation..

I tend to do that also :)

> Btw, uninitializedArray takes variadic arguments, how
> would I get the lengths of the dimensions as a tuple that can be
> passed in place of the variadic argument? I.e.:
>
> auto dupArray(int[][] src)  // say src is int[1][2]
> {
>    auto arr = uninitializedArray!(int[][])( /* need 1, 2 here */ );
>
>    // ..then copy each element..
> }

Having thought a bit more about this, there is a difference between static and dynamic arrays. For static arrays, the length is part of the type, so getting them should be straightforward.

Untested:

size_t[] arrayLengths(A)(A a) if (isStaticArray!A)
{
    static if (isStaticArray!(ElementType!A))
	return arrayLengths(a[0]) ~  a.length;
    else
        return [a.length];
}

But for dynamic arrays, int[][] can be a jagged (non square) array. And now that array literal are dynamic, the only way I see would be to collect the max length for all dimensions.

[[1,2,3],
 [4,5]]     -> 2 rows, 3 columns.

>> 3) I still think you should relax the constraint on the init value's type. You do not need it to be *exactly* BaseElementType!T. Thats stops you from writing
>>
>> auto arr2 = initializedArray!(float[][])(3,  2,3);
>
> I often fall to this trap. I think there's a syntax for checking if a type is implicitly convertible to another type?

There is  'is(A : B)', but when I tried this with your code, it didn't
work (maybe I was confused between double and floats). That's why I
used std.traits.isImplicitlyConvertible!(From,To)
December 21, 2011
On 12/21/11, Philippe Sigaud <philippe.sigaud@gmail.com> wrote:
> size_t[] arrayLengths(A)(A a) if (isStaticArray!A)
> {
>     static if (isStaticArray!(ElementType!A))
> 	return arrayLengths(a[0]) ~  a.length;
>     else
>         return [a.length];
> }

That returns an array, but I can't pass an array in place of a variadic argument.

The prototype of uninitializedArray is:
auto uninitializedArray(T, I...)(I sizes)
if(allSatisfy!(isIntegral, I)) { }
December 21, 2011
Ok just realized I can't use a mixin, lengths are dynamic, heheh. That went over my head. I'll see what else I can do..

On 12/21/11, Andrej Mitrovic <andrej.mitrovich@gmail.com> wrote:
> On 12/21/11, Philippe Sigaud <philippe.sigaud@gmail.com> wrote:
>> size_t[] arrayLengths(A)(A a) if (isStaticArray!A)
>> {
>>     static if (isStaticArray!(ElementType!A))
>> 	return arrayLengths(a[0]) ~  a.length;
>>     else
>>         return [a.length];
>> }
>
> That returns an array, but I can't pass an array in place of a variadic argument.
>
> The prototype of uninitializedArray is:
> auto uninitializedArray(T, I...)(I sizes)
> if(allSatisfy!(isIntegral, I)) { }
>