December 12, 2013
On Thursday, 12 December 2013 at 15:35:52 UTC, bearophile wrote:
> Ali Çehreli:
>
>> But look at the assertion: the type of the *slice* arr2 is int[3]. :)
>
> I didn't notice that. It looks strange... I don't understand it.
>
> Bye,
> bearophile

I already pointed out why it was that way AND that it's "fixed" now. ;)
December 12, 2013
Namespace:

> Your gig: https://github.com/D-Programming-Language/dmd/pull/2952#discussion_r8288045

This is part of the thread there:

>> Furhtermore, what if we indeed want to pass a dynamic array ?<<

Kenji> Use cast. In real world, if overloaded function takes both int[] and int[3], normally int[3] version would provide specialized implementation for 3 length arrays (eg. unroll the loop to operate each elements of the given array). Therefore force to invoke int[] version with array literal is not usual situation. Cast will fit in such case.<


If I have a function foo that takes a slice as input, and I want to pass it two arrays, the first time allocated on the heap and the second on the stack, I have to use an auxiliary variable:


void foo(int[]) {}
void main() {
    foo([1, 2, 3]);
    int[3] tmp = [4, 5, 6];
    foo(tmp);
}


DMD generates:

__Dmain comdat
L0:     push    EBX
        mov EAX,offset FLAT:_D11TypeInfo_Ai6__initZ
        push    3
        push    EAX
        call    near ptr __d_arrayliteralTX
        mov EBX,EAX
        mov dword ptr [EAX],1
        xor EAX,EAX
        mov dword ptr 4[EBX],2
        mov dword ptr 8[EBX],3
        add ESP,8
        pop EBX
        ret


With the []s syntax it should become:


void foo(int[]) {}
void main() {
    foo([1, 2, 3]);
    foo([4, 5, 6]s);
}


But I don't know how much common is such need.

In the Rust language when you write an array literal you always prefix it with a symbol, to tell the compiler where you want to allocate it. So I think it's not so useless :-)

Bye,
bearophile
December 13, 2013
Why don't you discuss on github?

And finally I did it:

----
auto[$] a_arr2 = dyn_arr[4 .. 8];
assert(is(typeof(a_arr2) == int[4]));
----

I will make a Pull Request tomorrow. Hope my code isn't that bad. :/
December 13, 2013
Namespace:

> Why don't you discuss on github?

I sometimes discuss on GitHub, but when the amount of things I have to say are large enough I think a forum like this is better. Also I don't like the lack of threading in GitHub comments.


> And finally I did it:
>
> ----
> auto[$] a_arr2 = dyn_arr[4 .. 8];
> assert(is(typeof(a_arr2) == int[4]));
> ----
>
> I will make a Pull Request tomorrow.

Good :-)

------------------

Regarding fixed sized arrays there's another point, visible here:

void main() {
    int[3] a, b, c;
    pragma(msg, typeof(a[] + b[]));
}

It prints:
int[]

So it seems the compiler loses track of the compile-time knowledge of the length of those arrays (it's probably caused by the slicing). In my opinion this is quite important because such loss of information makes it harder for the compiler to rewrite code as "c[] = a[] + b[]" as:

foreach (immutable i; 0 .. 3)
    c[i] = a[i] + b[i];

That later the back-end should unroll in just three sums (this is routinely done by the Fortran array ops); and a smart back-end can even rewrite with a single SIMD instruction (adding padding to the a, b, and c arrays making them 4 integers long).

Bye,
bearophile
December 13, 2013
On Thursday, 12 December 2013 at 18:20:25 UTC, bearophile wrote:
> Namespace:
>
>> Your gig: https://github.com/D-Programming-Language/dmd/pull/2952#discussion_r8288045
>
> This is part of the thread there:
>
>>> Furhtermore, what if we indeed want to pass a dynamic array ?<<
>
> Kenji> Use cast. In real world, if overloaded function takes both int[] and int[3], normally int[3] version would provide specialized implementation for 3 length arrays (eg. unroll the loop to operate each elements of the given array). Therefore force to invoke int[] version with array literal is not usual situation. Cast will fit in such case.<
>
>
> If I have a function foo that takes a slice as input, and I want to pass it two arrays, the first time allocated on the heap and the second on the stack, I have to use an auxiliary variable:
>
>
> void foo(int[]) {}
> void main() {
>     foo([1, 2, 3]);
>     int[3] tmp = [4, 5, 6];
>     foo(tmp);
> }

There's a known issue that the function foo takes the slice of stack allocated data. Today some peoples argue that it is unsafe operation and should be disallowed in @safe code.

> With the []s syntax it should become:
>
>
> void foo(int[]) {}
> void main() {
>     foo([1, 2, 3]);
>     foo([4, 5, 6]s);
> }
>
>
> But I don't know how much common is such need.
>
> In the Rust language when you write an array literal you always prefix it with a symbol, to tell the compiler where you want to allocate it. So I think it's not so useless :-)
>
> Bye,
> bearophile

I'm afraid that allowing foo([4, 5, 6]s) would easily cause memory corruption. I don't want to hurt language future by the trivial syntactic sugar.

Kenji Hara
December 13, 2013
On Friday, 13 December 2013 at 04:13:04 UTC, Kenji Hara wrote:
> On Thursday, 12 December 2013 at 18:20:25 UTC, bearophile wrote:
>> If I have a function foo that takes a slice as input, and I want to pass it two arrays, the first time allocated on the heap and the second on the stack, I have to use an auxiliary variable:
>>
>>
>> void foo(int[]) {}
>> void main() {
>>    foo([1, 2, 3]);
>>    int[3] tmp = [4, 5, 6];
>>    foo(tmp);
>> }
>
> There's a known issue that the function foo takes the slice of stack allocated data. Today some peoples argue that it is unsafe operation and should be disallowed in @safe code.
>
> Kenji Hara

I think there is consensus that in @safe code this should be blocked.
December 13, 2013
On Friday, December 13, 2013 07:19:50 Maxim Fomin wrote:
> On Friday, 13 December 2013 at 04:13:04 UTC, Kenji Hara wrote:
> > On Thursday, 12 December 2013 at 18:20:25 UTC, bearophile wrote:
> >> If I have a function foo that takes a slice as input, and I want to pass it two arrays, the first time allocated on the heap and the second on the stack, I have to use an auxiliary variable:
> >> 
> >> 
> >> void foo(int[]) {}
> >> void main() {
> >> 
> >>    foo([1, 2, 3]);
> >>    int[3] tmp = [4, 5, 6];
> >>    foo(tmp);
> >> 
> >> }
> > 
> > There's a known issue that the function foo takes the slice of stack allocated data. Today some peoples argue that it is unsafe operation and should be disallowed in @safe code.
> > 
> > Kenji Hara
> 
> I think there is consensus that in @safe code this should be blocked.

Slicing a static array is exactly the same as taking the address of a local variable, except that you then have a length in addition to the address. If that slice is assigned to anything which has a lifetime greater than that of the static array that was sliced, then the slice will be referring to invalid memory. That's clearly @system, and I don't see how anyone could even argue otherwise. Yes, there is plenty of code which is currently considered @safe by the compiler which will break once slicing a static array is considered @system like it needs to be (especially because static arrays are unfortunately automatically sliced when they're passed to a function which takes a dynamic array - I really wish that that were'n the case), but that can't be avoided. So, yes, changing it so that slicing a static array is @system will cause annoying code breakage, but I don't see any way around it without breaking what @safe means and does.

- Jonathan M Davis
December 13, 2013
On Friday, 13 December 2013 at 00:37:36 UTC, Namespace wrote:
> Why don't you discuss on github?
>
> And finally I did it:
>
> ----
> auto[$] a_arr2 = dyn_arr[4 .. 8];
> assert(is(typeof(a_arr2) == int[4]));
> ----
>
> I will make a Pull Request tomorrow. Hope my code isn't that bad. :/

Done:
https://github.com/D-Programming-Language/dmd/pull/2958
December 17, 2013
Namespace:

> Done:
> https://github.com/D-Programming-Language/dmd/pull/2958

If you have a situation like this:

int[3] foo() {
    typeof(return) a;
    return a;
}
void main() {
    int[100] b;
    b[0 .. 3] = foo();
}


Can you use code like this to infer the length of the part needed to copy?


int[3] foo() {
    typeof(return) a;
    return a;
}
void main() {
    int[100] b;
    b[0 .. $] = foo();
}


Bye,
bearophile
December 18, 2013
On Tuesday, 17 December 2013 at 17:01:55 UTC, bearophile wrote:
> Namespace:
>
>> Done:
>> https://github.com/D-Programming-Language/dmd/pull/2958
>
> If you have a situation like this:
>
> int[3] foo() {
>     typeof(return) a;
>     return a;
> }
> void main() {
>     int[100] b;
>     b[0 .. 3] = foo();
> }
>
>
> Can you use code like this to infer the length of the part needed to copy?
>
>
> int[3] foo() {
>     typeof(return) a;
>     return a;
> }
> void main() {
>     int[100] b;
>     b[0 .. $] = foo();
> }
>
>
> Bye,
> bearophile

No, not currently. But it is an interesting idea. Maybe I will implement this. And as far as I have enough time, I will also add test cases. Maybe on christmas. :)