February 13, 2020
On 2/13/2020 4:54 AM, Atila Neves wrote:
> https://en.wikipedia.org/wiki/Most_vexing_parse

Yes. There's no reason to support such things. C++ has to because it made a mistake early on.
February 14, 2020
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.

3) It's way, way too early to deprecate them. There is currently *no replacement available*. Some libraries try to keep compatibility for many versions (e.g. Vibe.d) and some projects tests with compilers that go way back (GDC-9 is the 2.076 FE and still used).

I tried to deprecate the `body` keyword after `do` has been in for 10 releases, and had to revert it (https://github.com/dlang/dmd/pull/10763) because it still causes too much breakage.

This fits your own definition of "shuffling things around to no benefit". I'm always happy to clean up the language, but it's a long and tedious process, and something that takes a lot of time in itself if we want to keep our users.
February 14, 2020
On Friday, 14 February 2020 at 05:53:08 UTC, 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);`.

You have auto?


>     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 } };
> }
> ```

This seems like a hole indeed. I wonder if it's worth considering though. My first thought is why is something that needs to be publicly constructed, not public? This looks fishy.

There's a very valid use case when it comes to returning voldermort types that match a specific interface (i.e. ranges), but I've never seen anyone construct them. And over here we have a declaration of a type, why is only the name private?

>
> To replace this usage, one has to use `typeof(Foo.ber)`. Even more verbose.
>
> 3) It's way, way too early to deprecate them. There is currently *no replacement available*. Some libraries try to keep compatibility for many versions (e.g. Vibe.d) and some projects tests with compilers that go way back (GDC-9 is the 2.076 FE and still used).

Yes, the deprecation should only happen after there's a replacement indeed (in general, not sure of that specific hole you showed above though).


February 14, 2020
On Friday, 14 February 2020 at 07:09:05 UTC, aliak wrote:
> On Friday, 14 February 2020 at 05:53:08 UTC, 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);`.
>
> You have auto?

The real inconvenience shows up as you nest structure, which was in the second part of the quote.

Consider `auto f = Foo(a: SomeType(b: SomeOtherType(x: 42)));`, it is not quite as readable as the struct literal alternative, and there's no way to use `auto` here, even though the expected type is known to the compiler and unambiguous.

And I didn't even mention templates! Imagine if a struct is an aggregate of other templated struct, e.g. `struct Aggregated (T, TV = DefaultValue) { Foo!T f1; Bar!T f2; xvector!(T, TV) f3; }`.
Have fun turning a struct literal for this into something that spells out the type.

I usually keep my type names verbose but my fields name short, and use struct literal all over the place. It leads to expressive code that is easy to read and easy to write, and feels familiar to people used to read JSON or YAML.

> [...]
>
> This seems like a hole indeed. I wonder if it's worth considering though. My first thought is why is something that needs to be publicly constructed, not public? This looks fishy.
>
> There's a very valid use case when it comes to returning voldermort types that match a specific interface (i.e. ranges), but I've never seen anyone construct them. And over here we have a declaration of a type, why is only the name private?
>

I would strongly advise against trying to decide what is a "valid" use case. Just because someone approach a problem differently doesn't mean their solution is invalid.


> Yes, the deprecation should only happen after there's a replacement indeed (in general, not sure of that specific hole you showed above though).

The point was that when we replace a feature, it should take years before the old version is deprecated if we want to be taken seriously as a language.
February 14, 2020
On 2020-02-13 12:54:26 +0000, Atila Neves said:

>> I never understood (but expect some good reason to exists) why I can't write:
>> 
>> S s(1,2);
>> 
>> which IMO is the most compact and clear form.
> 
> https://en.wikipedia.org/wiki/Most_vexing_parse

As I expected... thanks for the reference.

-- 
Robert M. Münch
http://www.saphirion.com
smarter | better | faster

February 14, 2020
On Friday, 14 February 2020 at 07:54:56 UTC, Mathias Lang wrote:
>> You have auto?
>
> The real inconvenience shows up as you nest structure, which was in the second part of the quote.
>
> Consider `auto f = Foo(a: SomeType(b: SomeOtherType(x: 42)));`, it is not quite as readable as the struct literal alternative, and there's no way to use `auto` here, even though the expected type is known to the compiler and unambiguous.

I'm not sure I see where you're repeating types there. As for readability, I find

Foo f = { ber: { a: 42, b: 84 } };

Less readable than:

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

(I've duplicated your spacing choices, but the extra type information is more useful to me at the call site).

>
> And I didn't even mention templates! Imagine if a struct is an aggregate of other templated struct, e.g. `struct Aggregated (T, TV = DefaultValue) { Foo!T f1; Bar!T f2; xvector!(T, TV) f3; }`.
> Have fun turning a struct literal for this into something that spells out the type.

That'd be not fun regardless of brace initializers or not.

>
> I would strongly advise against trying to decide what is a "valid" use case. Just because someone approach a problem differently doesn't mean their solution is invalid.

If there's a bug in the type system it should be fixed. Not maintained. Not thinking about is would be the unadvisable part IMO.

February 14, 2020
On Friday, 14 February 2020 at 13:47:38 UTC, aliak wrote:
> On Friday, 14 February 2020 at 07:54:56 UTC, Mathias Lang wrote:
>>> You have auto?
>>
>> The real inconvenience shows up as you nest structure, which was in the second part of the quote.
>>
>> Consider `auto f = Foo(a: SomeType(b: SomeOtherType(x: 42)));`, it is not quite as readable as the struct literal alternative, and there's no way to use `auto` here, even though the expected type is known to the compiler and unambiguous.
>
> I'm not sure I see where you're repeating types there. As for readability, I find
>
> Foo f = { ber: { a: 42, b: 84 } };
>
> Less readable than:
>
> auto f = Foo( ber: Ber( a: 42, b: 84 ) );
>
> (I've duplicated your spacing choices, but the extra type information is more useful to me at the call site).

In this case I prefer the First one:

> Foo f = { ber: { a: 42, b: 84 } };

Matheus.
February 14, 2020
On Friday, 14 February 2020 at 07:54:56 UTC, Mathias Lang wrote:
> The real inconvenience shows up as you nest structure, which was in the second part of the quote.
>
> Consider `auto f = Foo(a: SomeType(b: SomeOtherType(x: 42)));`, it is not quite as readable as the struct literal alternative, and there's no way to use `auto` here, even though the expected type is known to the compiler and unambiguous.
>
> And I didn't even mention templates! Imagine if a struct is an aggregate of other templated struct, e.g. `struct Aggregated (T, TV = DefaultValue) { Foo!T f1; Bar!T f2; xvector!(T, TV) f3; }`.
> Have fun turning a struct literal for this into something that spells out the type.
>
> I usually keep my type names verbose but my fields name short, and use struct literal all over the place. It leads to expressive code that is easy to read and easy to write, and feels familiar to people used to read JSON or YAML.
>

Perhaps declarative programming should be a first class feature, instead of using struct initializers to emulate it.

The syntax could be similar to QML/DML:

struct Type
{
    string field1;
    string field2;
    NestedField field3;

    struct NestedField
    {
        int field1;
    }
}

struct AnotherType
{
    int field1;
}

declare instance1 : Type
{
    field1: "value";
    field2: "value2";
    field3.field1: 100;
    int field4: 5;

    AnotherType {
        field1: outer.field4 + 9;
    }
}

Lowers to something like:
struct __instance1
{
    Type __type;
    alias type this;
    AnotherType __child_0;
    __constructor() {
        __type.field1 = "value";
        __type.field2 = "value2";
        __type.field3.field1 = 100;
        __child_0.field1 = __type.field4 + 9;
    }
}
__instance1 instance1;

February 14, 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
February 14, 2020
On Friday, 14 February 2020 at 14:46:43 UTC, Steven Schveighoffer wrote:
> 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

I was thinking of this when you brought up that issue.
https://github.com/dotnet/csharplang/issues/100

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