DIP 1031--Deprecate Brace-Style Struct Initializers--Community Review Round 1 Discussion

Steven Schveighoffer schveiguy at gmail.com
Fri Feb 14 14:46:43 UTC 2020


On 2/14/20 12:53 AM, Mathias Lang wrote:
> On Thursday, 13 February 2020 at 07:29:00 UTC, Mike Parker wrote:
>> This is the feedback thread for the first round of Community Review 
>> for DIP 1031, "Deprecate Brace-Style Struct Initializers":
>>
>> https://github.com/dlang/DIPs/blob/c0c1c9f9665e0bc1db611f4e93e793d64451f763/DIPs/DIP1031.md 
>>
> 
> 
> I think this is heading in the right direction, however I see three issues:
> 
> 1) The type name has to be repeated.
>      So as mentioned, `Foo f = (42, 84);` would be more readable than 
> `Foo f = Foo(42, 84);`.
>      This gets worse when a struct contains nested struct definitions, 
> as Andre pointed out (here: 
> https://github.com/dlang/DIPs/pull/169#issuecomment-532830320).
> 
> 2) It's actually part of 1, but I wanted to make it a separate issue 
> because it's important. Not *all* usages of struct initializer can be 
> replaced by the constructor syntax. For example:
> ```
> --- definition.d
> module definition;
> 
> struct Foo
> {
>      private struct Bar
>      {
>          int a;
>          int b;
>      }
> 
>      Bar ber;
> }
> 
> --- main.d
> module main;
> import definition;
> 
> void main ()
> {
>      Foo f = { ber: { a: 42, b: 84 } };
> }
> ```
> 
> To replace this usage, one has to use `typeof(Foo.ber)`. Even more verbose.
> 

This is probably less of a problem. If you need to initialize items via 
static construction with a private type, chances are the library gives 
you a mechanism to do that.

However even when you have public access to the name, but the name is 
unwieldy (e.g. the templates in your followup message), makes this look 
like a bigger problem than the simple examples. Imagine a struct with a 
static array of structs. Currently you can do this:

struct Vector2D
{
   float x;
   float y;
}
struct Moves
{
    Vector2D[4] items;
}

Moves awsd = {items: [{x: 1, y: 0}, {x: 0, y: 1}, {x: -1, y: 0}, {x:0, 
y:-1}]};

But with this DIP, the call now becomes:

Moves awsd = Moves(items: [Vector2D(x: 1, y: 0), Vector2D(x: 0, y: 1), 
Vector2D(x: -1, y: 0), Vector2D(x:0, y:-1)]);

Now, imagine Vector2D and Moves are templated on type! Would be horrendous.

I can think of a solution though, just have a substitute for the real 
name of the type for struct initializers. In other words, this is not a 
function call, and does not have possible overloads. Something like:

Foo f = Foo(ber: auto(a: 42, b: 84));

It's not as terse, but circumvents for the most part the issue of long 
names.

You could even just keep the initializer syntax but with parentheses 
instead of braces:

Foo f = Foo(ber: (a: 42, b: 84)); // only valid for struct 
initialization without a ctor.

I think this would be unambiguous. But at that point, why are we even 
deprecating the current syntax?

Indeed, I think instead of deprecation, we should first just provide the 
alternative, and see how it goes.

I'm also not sure we even need to deprecate this feature. We aren't 
gaining anything syntax-wise, and it's not harmful for the compiler to 
support it as far as I can tell.

-Steve


More information about the Digitalmars-d mailing list