May 01, 2021

On Saturday, 1 May 2021 at 12:35:00 UTC, Adam D. Ruppe wrote:

>

Yeah, it works now but that's again relatively new. It wasn't there when this stuff was designed.

It'd probably break a lot of code if this were to change now.

I guess the conclusion is, D's array literals are weird for historic reasons.

There are definitely more important things that need fixing. This would be a breaking change with relatively not that much benefit.

The .staticArray thing is good enough for me.

Still there is some performance / language simplification to be gained here.

May 01, 2021

On Saturday, 1 May 2021 at 12:27:30 UTC, Blatnik wrote:

>

I still see no reason [1, 2, 3] should ever not be considered a int[3], unless you explicitly ask for it:

I strongly disagree. That array literals produce dynamic arrays made sense to me from the day I found D, and it still makes sense 18 years later.

If they were to produce static arrays, then what happens here?

int[] a = [1, 2, 3];
return a;

In order for this to work as expected, then this particular literal would have to be allocated on the GC heap, which is then inconsistent with the normal behavior. Right now, the compiler is free to elide allocations for literals when it can, but that's not an optimization, not an inconsistency.

And what about this?

doSomeMatrixStuff3x3(
    [1.0, 0.0, 0.0,
     0.0, 1.0, 0.0,
     0.0, 0.0, 1.0]
);

Now I'm passing 9 floats by value unless I remember to do whatever needs to be done to indicate that this should be dynamic (.dup).

Static array literals just seem backwards to me. With dynamic array literals, I don't have to think about it.

Moreover, I really would hate to see either @nogc or BetterC have any impact on language changes. Those are the exceptional cases. D is a GC'ed language. @nogc and BetterC are more restricted subsets.

May 01, 2021

On Saturday, 1 May 2021 at 15:14:49 UTC, Mike Parker wrote:

>

but that's not an optimization, not an inconsistency.

but that's an optimization...

May 01, 2021

On Saturday, 1 May 2021 at 11:32:47 UTC, Blatnik wrote:

>

Why? What's the reason for this design?

As mentioned before, static arrays have limited life time, so the compiler allocates arrays using the GC unless it is certain no references to it could escape.

>

It also means that functions that take a slice parameter:

void foo(int[] bar);

Can't be called naturally in @nogc or -betterC.

foo([1, 2, 3]) // Error: Array literal may cause GC allocation.

In this case, foo could e.g. store bar in a global variable causing memory corruption. It does work in -betterC if you add scope to the parameter, which means that bar is not allowed to leave the scope of the function:

void foo(scope int[] bar) @nogc {}

extern(C) void main() @nogc {
    foo([1, 2, 3]);
}
>

This decision to make array literals slice types by default seems like a bad idea in all respects. It should be changed, array literals (are) should be fixed size.

It would have to be done in a backwards compatible way, array literals are too common to introduce a breaking change.

>

Any thoughts?

D's literals are full of somewhat ad-hoc rules that allow / disallow certain assignments that don't follow from their types.

  • a string literal converts to a C-style string const(char)*, but a string does not convert to a const(char)*
  • an integer literal converts to a short if it fits, though int does not convert to short (this is called "value range propagation")
  • an integer array literal [1, 2, 3] converts to a float[], though an int[] does not convert to float[]
  • conversely, an invalid code point 0x110000 can not be assigned to a dchar, even though int converts to dchar

The fact that static arrays are initialized using dynamic array literals is another instance of this. I'd personally be in favor of dedicated static array literals, but I'm afraid most people are satisfied with import std.array: staticArray;.

May 01, 2021

On Saturday, 1 May 2021 at 15:14:49 UTC, Mike Parker wrote:

>

I strongly disagree. That array literals produce dynamic arrays made sense to me from the day I found D, and it still makes sense 18 years later.

I really can't argue here. If you just want to not think about it, then having it always be dynamically allocated is the way to go.

But isn't D a systems level programming language where you do want to care about things like what is dynamically allocated and what isn't? :D

If so then the language should encourage you to allocate statically wherever possible. At least in my view.

>

If they were to produce static arrays, then what happens here?

int[] a = [1, 2, 3];
return a;

Well the way I saw my idea working is that the compiler would give you a hard error here, and tell you to fix it by allocating it with return a.dup if that's what you wanted, or make the function return a static array if that's what you wanted.

>

And what about this?

doSomeMatrixStuff3x3(
    [1.0, 0.0, 0.0,
     0.0, 1.0, 0.0,
     0.0, 0.0, 1.0]
);

Now I'm passing 9 floats by value unless I remember to do whatever needs to be done to indicate that this should be dynamic (.dup).

Unless doSomeMatrixStuff3x3 does something stupid like copying the slice to a global variable, then you don't need to dynamically allocate the temporary before you pass it in anyway. So if the array literals were static, the compiler would turn the call above into something like:

float[9] __temporary = [1, 0, 0, 0, 1, 0, 0, 0, 1];
doSomeMatrixStuff3x3(__temporary[]);

This is what you end up doing in -betterC and @nogc anyway, and without them this will still save you an unnecessary allocation.

Note that if doSomeMatrixStuff3x3 does save the slice to a global variable or something, that's already incorrect today, as you could in theory pass in a stack allocated static array as a slice (exactly like it is being called above).

>

Moreover, I really would hate to see either @nogc or BetterC have any impact on language changes. Those are the exceptional cases. D is a GC'ed language. @nogc and BetterC are more restricted subsets.

I see your point. This change would make code without @nogc slightly more annoying to write because of the error messages when you try to do something like the above, which is fine to do right now.

But I guess in my view this could be a (slightly) helpful change for (every subset of) the language.

May 01, 2021

On Saturday, 1 May 2021 at 12:22:50 UTC, evilrat wrote:

>

On Saturday, 1 May 2021 at 11:50:27 UTC, Adam D. Ruppe wrote:

>

or you can use the library .staticArray thing to expressly indicate your intention on the original foo

foo([1,2,3].staticArray);

Is there one in Phobos? Anyway this works, but maybe it can be made more type safe with constraints or just with improved symtax.

// compiles with -vgc and -betterC (weird, also without import stdc.core.stdio)
import std.range : ElementType;

template staticArray(alias T)
{
	enum ElementType!(typeof(T))[T.length] staticArray = T;
}

extern(C) void main()
{
	import core.stdc.stdio;
	auto arr = staticArray!([1,2,3]);
	pragma(msg, typeof(arr)); // int[3]
	foreach(i; arr)
		printf("%d\n", i);
}

don't you realize something is weird?

someone is asking to be able to do auto a = [1, 2, 3]

and you propose a template?

this is asking people to look for alternative language

auto a = new[1,2,3] <== this should be allocated array
auto a = [1,2,3] <== this should be static array

let's fix that, shall we? instead of telling people to bloat their files with templates

May 01, 2021

On Saturday, 1 May 2021 at 18:57:48 UTC, Blatnik wrote:

>

But isn't D a systems level programming language where you do want to care about things like what is dynamically allocated and what isn't? :D

D is an all-purpose programming language. Some purposes are easier or harder than others. The easier thing tries to be more correct than not, even if that means extra performance may take extra work.

May 01, 2021

On Saturday, 1 May 2021 at 18:57:48 UTC, Blatnik wrote:

>
float[9] __temporary = [1, 0, 0, 0, 1, 0, 0, 0, 1];
doSomeMatrixStuff3x3(__temporary[]);

This is what you end up doing in -betterC and @nogc anyway, and without them this will still save you an unnecessary allocation.

The stack propagation is unrelated to -betterC, it only depends on the parameter being marked as scope.

May 02, 2021

On Saturday, 1 May 2021 at 19:49:51 UTC, russhy wrote:

>

On Saturday, 1 May 2021 at 12:22:50 UTC, evilrat wrote:

>

On Saturday, 1 May 2021 at 11:50:27 UTC, Adam D. Ruppe wrote:

>

or you can use the library .staticArray thing to expressly indicate your intention on the original foo

foo([1,2,3].staticArray);

Is there one in Phobos? Anyway this works, but maybe it can be made more type safe with constraints or just with improved symtax.

// compiles with -vgc and -betterC (weird, also without import stdc.core.stdio)
import std.range : ElementType;

template staticArray(alias T)
{
	enum ElementType!(typeof(T))[T.length] staticArray = T;
}

extern(C) void main()
{
	import core.stdc.stdio;
	auto arr = staticArray!([1,2,3]);
	pragma(msg, typeof(arr)); // int[3]
	foreach(i; arr)
		printf("%d\n", i);
}

don't you realize something is weird?

someone is asking to be able to do auto a = [1, 2, 3]

and you propose a template?

this is asking people to look for alternative language

auto a = new[1,2,3] <== this should be allocated array
auto a = [1,2,3] <== this should be static array

let's fix that, shall we? instead of telling people to bloat their files with templates

You see only what you wanted to see.

Let me clarify something.
That code proves that unlike it was stated "array type information is gone" it actually isn't, which this code proves.
It provides workaround just is case.
I'm not forcing anyone to use it, and there is simpler solution (still a template one) in phobos.
And finally, I haven't said anything like "D DONT NEED THIS, STFU AND USE HACKS".

But after recent discussion you seem to trigger just by seeing my posts. No thanks I don't need any stalkers following me around.

May 02, 2021

On Saturday, 1 May 2021 at 19:49:51 UTC, russhy wrote:

>

On Saturday, 1 May 2021 at 12:22:50 UTC, evilrat wrote:

>

On Saturday, 1 May 2021 at 11:50:27 UTC, Adam D. Ruppe wrote:

>

[...]

Is there one in Phobos? Anyway this works, but maybe it can be made more type safe with constraints or just with improved symtax.

// compiles with -vgc and -betterC (weird, also without import stdc.core.stdio)
import std.range : ElementType;

template staticArray(alias T)
{
	enum ElementType!(typeof(T))[T.length] staticArray = T;
}

extern(C) void main()
{
	import core.stdc.stdio;
	auto arr = staticArray!([1,2,3]);
	pragma(msg, typeof(arr)); // int[3]
	foreach(i; arr)
		printf("%d\n", i);
}

don't you realize something is weird?

someone is asking to be able to do auto a = [1, 2, 3]

and you propose a template?

this is asking people to look for alternative language

auto a = new[1,2,3] <== this should be allocated array
auto a = [1,2,3] <== this should be static array

let's fix that, shall we? instead of telling people to bloat their files with templates

Is there any way to enable this in the language?

auto a = [1,2,3] + [4,5,6]; //[5,7,9]

I want to allow the operation.

If I made a dmd fork, could I change this behavior "easily" or would it require a blood sacrifice