www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - DIP 1031--Deprecate Brace-Style Struct Initializers--Community Review

reply Mike Parker <aldacron gmail.com> writes:
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

Here in the discussion thread, you are free to discuss anything 
and everything related to the DIP. Express your support or 
opposition, debate alternatives, argue the merits... in other 
words, business as usual.

However, if you have any specific feedback for how to improve the 
the proposal itself, then please post it in the feedback thread. 
The feedback thread will be the source for the review summary I 
write at the end of this review round. I will post a link to that 
thread immediately following this post. Just be sure to read and 
understand the Reviewer Guidelines before posting there:

https://github.com/dlang/DIPs/blob/master/docs/guidelines-reviewers.md

The review period will end at 11:59 PM ET on February 27, or when 
I make a post declaring it complete. Discussion in this thread 
may continue beyond that point.

At the end of Round 1, if further review is deemed necessary, the 
DIP will be scheduled for another round of Community Review. 
Otherwise, it will be queued for the Final Review and Formal 
Assessment.

Please stay on topic here. I will delete posts that are 
completely off topic.
Feb 12
next sibling parent reply Mike Parker <aldacron gmail.com> writes:
On Thursday, 13 February 2020 at 07:29:00 UTC, Mike Parker wrote:
 However, if you have any specific feedback for how to improve 
 the the proposal itself, then please post it in the feedback 
 thread. The feedback thread will be the source for the review 
 summary I write at the end of this review round. I will post a 
 link to that thread immediately following this post.
The Feedback thread is here: https://forum.dlang.org/post/iywiuqqmevdghgbyrved forum.dlang.org
Feb 12
parent reply Paolo Invernizzi <paolo.invernizzi gmail.com> writes:
On Thursday, 13 February 2020 at 07:30:49 UTC, Mike Parker wrote:
 On Thursday, 13 February 2020 at 07:29:00 UTC, Mike Parker 
 wrote:
 However, if you have any specific feedback for how to improve 
 the the proposal itself, then please post it in the feedback 
 thread. The feedback thread will be the source for the review 
 summary I write at the end of this review round. I will post a 
 link to that thread immediately following this post.
The Feedback thread is here: https://forum.dlang.org/post/iywiuqqmevdghgbyrved forum.dlang.org
It makes me a little sad to read "With the adoption of named argument lists ..." I'm wondering if discussing about the opportunity or not to add a feature worths the time, as every decision seems already taken 'a priori'. Anyway, as it seems that named arguments is 'de-facto' approved, this DIP is the natural consequence, so that's fine.
Feb 13
parent reply Mike Parker <aldacron gmail.com> writes:
On Thursday, 13 February 2020 at 08:22:19 UTC, Paolo Invernizzi 
wrote:

 It makes me a little sad to read "With the adoption of named 
 argument lists ..."

 I'm wondering if discussing about the opportunity or not to add 
 a feature worths the time, as every decision seems already 
 taken 'a priori'.

 Anyway, as it seems that named arguments is 'de-facto' 
 approved, this DIP is the natural consequence, so that's fine.
Please note the DIP also says: "This DIP presumes the acceptance of DIP 1030: Named Arguments." And in an effort to preempt comments like your, I explicitly left this note in the feedback thread: "Please note that acceptance of this DIP is dependent upon acceptance of DIP 1030. If that DIP is rejected, this DIP will move into "Postponed" for an extended period to allow time for alternative named argument proposals." I should have left it here, too :-) Anyway, 1030 is likely to be accepted, but it isn't a given. Walter has pulled two of his DIPs in the past in response to community feedback, so please don't think any his DIPs is a rubber stamp. However, if it *is* accepted, then it saves time if we have both DIPs going through the review process close together. That's all this is.
Feb 13
parent reply Paolo Invernizzi <paolo.invernizzi gmail.com> writes:
On Thursday, 13 February 2020 at 08:46:31 UTC, Mike Parker wrote:
 On Thursday, 13 February 2020 at 08:22:19 UTC, Paolo Invernizzi 
 wrote:

 [...]
Please note the DIP also says: "This DIP presumes the acceptance of DIP 1030: Named Arguments." And in an effort to preempt comments like your, I explicitly left this note in the feedback thread: "Please note that acceptance of this DIP is dependent upon acceptance of DIP 1030. If that DIP is rejected, this DIP will move into "Postponed" for an extended period to allow time for alternative named argument proposals." I should have left it here, too :-) Anyway, 1030 is likely to be accepted, but it isn't a given. Walter has pulled two of his DIPs in the past in response to community feedback, so please don't think any his DIPs is a rubber stamp. However, if it *is* accepted, then it saves time if we have both DIPs going through the review process close together. That's all this is.
Acknowledged, sorry for that ... I need to remember to take the morning coffe before posting ... eheh Anyway, the DIP is fine, I've always hated brace-style struct initializers, let's kill them with fire.
Feb 13
parent reply Guillaume Piolat <first.last gmail.com> writes:
On Thursday, 13 February 2020 at 08:52:41 UTC, Paolo Invernizzi 
wrote:
 Anyway, the DIP is fine, I've always hated brace-style struct 
 initializers, let's kill them with fire.
13 years of D and I didn't know brace-style struct initializers even existed... Sounds error prone.
Feb 15
next sibling parent Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Saturday, February 15, 2020 5:50:15 AM MST Guillaume Piolat via 
Digitalmars-d wrote:
 On Thursday, 13 February 2020 at 08:52:41 UTC, Paolo Invernizzi

 wrote:
 Anyway, the DIP is fine, I've always hated brace-style struct
 initializers, let's kill them with fire.
13 years of D and I didn't know brace-style struct initializers even existed... Sounds error prone.
I tend to forget that the syntax exists, and I never use it, but it's probably less error-prone than using the constructor syntax with a struct that has no constructors, since it's at least lining up the field initializers with the fields by name, meaning that if fields are added, removed, and/or rearranged over time, you won't end up with existing code initializing the wrong fields. If you use the constructor syntax with a struct that has no constructors, then it just sets the fields in order, and if you provide fewer initializers than there are fields, then the rest just get default-initialized. And while that can be fine when you first declare the struct, it can be very error-prone if the struct's fields are ever changed later, since existing code may still compile but then end up setting the wrong fields. It's why I pretty much always declare constructors for structs even if they're just POD types where all of the members are public. - Jonathan M Davis
Feb 21
prev sibling parent Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Friday, February 21, 2020 8:19:34 AM MST Jonathan M Davis via 
Digitalmars-d wrote:
 On Saturday, February 15, 2020 5:50:15 AM MST Guillaume Piolat via

 Digitalmars-d wrote:
 On Thursday, 13 February 2020 at 08:52:41 UTC, Paolo Invernizzi

 wrote:
 Anyway, the DIP is fine, I've always hated brace-style struct
 initializers, let's kill them with fire.
13 years of D and I didn't know brace-style struct initializers even existed... Sounds error prone.
I tend to forget that the syntax exists, and I never use it, but it's probably less error-prone than using the constructor syntax with a struct that has no constructors, since it's at least lining up the field initializers with the fields by name, meaning that if fields are added, removed, and/or rearranged over time, you won't end up with existing code initializing the wrong fields. If you use the constructor syntax with a struct that has no constructors, then it just sets the fields in order, and if you provide fewer initializers than there are fields, then the rest just get default-initialized. And while that can be fine when you first declare the struct, it can be very error-prone if the struct's fields are ever changed later, since existing code may still compile but then end up setting the wrong fields. It's why I pretty much always declare constructors for structs even if they're just POD types where all of the members are public.
Ouch. I didn't read carefully enough. I wasn't aware that the brace style for struct initialization works without providing field names. That just seems redundant with the constructor syntax, and it has all of the same problems that you get with using the constructor syntax without a constructor, which is something that I'm inclined to think is bad practice due to how error-prone it can be as code is changed over time. - Jonathan M Davis
Feb 21
prev sibling next sibling parent Basile B. <b2.temp gmx.com> writes:
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":
I'm in favor of a change. So there were two options 1. StructInitializers could have become StructLiterals, ie. a primary expression, i.e usable in all contexts, not only as initializer. 2. Kill them. By removing them you can now get rid of the special AST node for initializers. After the removal it will be either an array literal (so a primary), an AA literal (so a primary) or an expression, in other words always an expression. This option is also good to simplify the parser because struct literals could look like func literals without a full, arbitrarily long lookup. Nobody wrote a proposal for 1. so let it be 2. End of story from my point of view.
Feb 13
prev sibling next sibling parent reply IGotD- <nise nise.com> writes:
According to the DIP

This will be deprecated.

struct S { int a, b; }

S s = { 1, 2 }; // Deprecated: use S(1, 2) instead


So after this DIP we would write

S s = S(1, 2);

instead.

However, would

S s = (1, 2);

be allowed inferring the type?


Would there be case where this type of initialization would mask 
the constructor of a type or vice versa?

Ex.

struct S
{
     int a, b;
     this(int bp, int ap)
     {
         a = ap;
         b = bp;
     }
}

writing

S s = S(1, 2);

what would it pick?
Feb 13
next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 2/13/2020 1:47 AM, IGotD- wrote:
 However, would
 
 S s = (1, 2);
 
 be allowed inferring the type?
No. But you can write: auto s = S(1, 2);
 Would there be case where this type of initialization would mask the
constructor 
 of a type or vice versa?
The constructor takes precedence.
 struct S
 {
      int a, b;
      this(int bp, int ap)
      {
          a = ap;
          b = bp;
      }
 }
 
 writing
 
 S s = S(1, 2);
 
 what would it pick?
The constructor.
Feb 13
next sibling parent reply Mike Parker <aldacron gmail.com> writes:
On Thursday, 13 February 2020 at 09:56:27 UTC, Walter Bright 
wrote:
 Would there be case where this type of initialization would 
 mask the constructor of a type or vice versa?
The constructor takes precedence.
 struct S
 {
      int a, b;
      this(int bp, int ap)
      {
          a = ap;
          b = bp;
      }
 }
 
 writing
 
 S s = S(1, 2);
 
 what would it pick?
The constructor.
Which, for the record, is the current behavior. Unfortunately, the struct literal documentation only mentions opCall. I'll submit a PR. https://dlang.org/spec/struct.html#struct-literal
Feb 13
parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 2/13/20 4:59 AM, Mike Parker wrote:
 On Thursday, 13 February 2020 at 09:56:27 UTC, Walter Bright wrote:
 Would there be case where this type of initialization would mask the 
 constructor of a type or vice versa?
The constructor takes precedence.
 struct S
 {
      int a, b;
      this(int bp, int ap)
      {
          a = ap;
          b = bp;
      }
 }

 writing

 S s = S(1, 2);

 what would it pick?
The constructor.
Which, for the record, is the current behavior. Unfortunately, the struct literal documentation only mentions opCall. I'll submit a PR. https://dlang.org/spec/struct.html#struct-literal
That page is *really* old. I think what Mike meant to say is that struct initializers and struct literals are both disabled once a constructor or opCall function is present. So in essence, the above struct S could NEVER be initialized except via constructor or with it's .init value. Having the named parameter DIP accepted means that now the constructor becomes possible to call like the initializer, assuming you gave bp and ap default values. -Steve
Feb 13
parent reply IGotD- <nise nise.com> writes:
On Thursday, 13 February 2020 at 13:05:19 UTC, Steven 
Schveighoffer wrote:
 That page is *really* old. I think what Mike meant to say is 
 that struct initializers and struct literals are both disabled 
 once a constructor or opCall function is present.

 So in essence, the above struct S could NEVER be initialized 
 except via constructor or with it's .init value. Having the 
 named parameter DIP accepted means that now the constructor 
 becomes possible to call like the initializer, assuming you 
 gave bp and ap default values.

 -Steve
Isn't that a bit restrictive? Wouldn't you like to have a constructor and sometimes parenthesis style initialization? With using parenthesis for everything there will be an ambiguity. In that case keeping () for constructor and {} for initialization would make it clear what the programmer wants. If the compiler cannot match a constructor it can go on and use initialization instead. Would this be too allowing and lead to that programmer errors are missed?
Feb 13
next sibling parent Steven Schveighoffer <schveiguy gmail.com> writes:
On 2/13/20 10:49 AM, IGotD- wrote:
 On Thursday, 13 February 2020 at 13:05:19 UTC, Steven Schveighoffer wrote:
 That page is *really* old. I think what Mike meant to say is that 
 struct initializers and struct literals are both disabled once a 
 constructor or opCall function is present.

 So in essence, the above struct S could NEVER be initialized except 
 via constructor or with it's .init value. Having the named parameter 
 DIP accepted means that now the constructor becomes possible to call 
 like the initializer, assuming you gave bp and ap default values.
Isn't that a bit restrictive? Wouldn't you like to have a constructor and sometimes parenthesis style initialization? With using parenthesis for everything there will be an ambiguity. In that case keeping () for constructor and {} for initialization would make it clear what the programmer wants. If the compiler cannot match a constructor it can go on and use initialization instead. Would this be too allowing and lead to that programmer errors are missed?
You misunderstand. {} intialization today does not work when a constructor is defined: struct S { int a; this(int a) {this.a = a; } } void main() { S s = {a: 1}; } Error: struct S has constructors, cannot use { initializers }, use S( initializers ) instead So the only place this DIP would deprecate valid code is for structs without ctors. -Steve
Feb 13
prev sibling parent Walter Bright <newshound2 digitalmars.com> writes:
On 2/13/2020 7:49 AM, IGotD- wrote:
 Isn't that a bit restrictive?
Yes, and it's on purpose. Note that this applies to C++ as well. If all the constructor does is supply its arguments to the fields, there's not point in providing one. If it does more than that, by using literals the user could bypass that, which would be a clear code smell if not an outright bug. Worse, it would be difficult to QA the code as the constructor call would look just like an initializer.
Feb 13
prev sibling parent reply =?iso-8859-1?Q?Robert_M._M=FCnch?= <robert.muench saphirion.com> writes:
On 2020-02-13 09:56:27 +0000, Walter Bright said:

 On 2/13/2020 1:47 AM, IGotD- wrote:
 However, would
 
 S s = (1, 2);
 
 be allowed inferring the type?
No. But you can write: auto s = S(1, 2);
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. -- Robert M. Mnch http://www.saphirion.com smarter | better | faster
Feb 13
next sibling parent Basile B. <b2.temp gmx.com> writes:
On Thursday, 13 February 2020 at 11:04:26 UTC, Robert M. Münch 
wrote:
 I never understood (but expect some good reason to exists) why 
 I can't write:

 S s(1,2);
It would only work in the context of a declaration, otherwise it's a CallExpression.
Feb 13
prev sibling parent reply Atila Neves <atila.neves gmail.com> writes:
On Thursday, 13 February 2020 at 11:04:26 UTC, Robert M. Münch 
wrote:
 On 2020-02-13 09:56:27 +0000, Walter Bright said:

 On 2/13/2020 1:47 AM, IGotD- wrote:
 However, would
 
 S s = (1, 2);
 
 be allowed inferring the type?
No. But you can write: auto s = S(1, 2);
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
Feb 13
next sibling parent Walter Bright <newshound2 digitalmars.com> writes:
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.
Feb 13
prev sibling parent =?iso-8859-1?Q?Robert_M._M=FCnch?= <robert.muench saphirion.com> writes:
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. Mnch http://www.saphirion.com smarter | better | faster
Feb 14
prev sibling parent Petar Kirov [ZombineDev] <petar.p.kirov gmail.com> writes:
On Thursday, 13 February 2020 at 09:47:13 UTC, IGotD- wrote:
 According to the DIP

 This will be deprecated.

 struct S { int a, b; }

 S s = { 1, 2 }; // Deprecated: use S(1, 2) instead


 So after this DIP we would write

 S s = S(1, 2);

 instead.

 However, would

 S s = (1, 2);

 be allowed inferring the type?
This is allowed today: auto s = S(1, 2); This as well: alias args = AliasSeq!(1, 2); auto s = S(args); S s2 = S(args); If this was accepted: alias args = AliasSeq!(1, 2); S s = args; We could also write: S s = AliasSeq!(1, 2); And also, if Timon's proposal [1] is accepted, we would get built-in syntax for AliasSeq-es, so we would finally be able to write: S s = (1, 2); [1]: https://github.com/tgehr/DIPs/blob/tuple-syntax/DIPs/DIP1xxx-tg.md
 Would there be case where this type of initialization would 
 mask the constructor of a type or vice versa?

 Ex.

 struct S
 {
     int a, b;
     this(int bp, int ap)
     {
         a = ap;
         b = bp;
     }
 }

 writing

 S s = S(1, 2);

 what would it pick?
A user-defined constructor prevents the generation of a compiler-synthesized one. In the code above, the result is `S(2, 1)`, i.e. `1` is assigned to `S.a` and `2` to `S.b`. This DIP won't change anything in this regard.
Feb 13
prev sibling next sibling parent Donald <donald outlook.com> writes:
On Thursday, 13 February 2020 at 07:29:00 UTC, Mike Parker wrote:
 ...
Well first I'm not against this, but one thing that called my attention is that a while ago Manu proposed a DIP which was rejected (https://github.com/dlang/DIPs/blob/c0c1c9f9665e0bc1db611f4e93e793d64451f763/DIPs/rejected/DIP1016.md) In that case Walter/Andrei bashed that DIP for lack of rationale/description/cases and so on. I remember Andrei telling in this Forum, how a DIP should be written and he asked for a professional analysis and so on. Now this DIP is very thin (I think it couldn't fill a A4 paper) and I'm seeing this trending in every Walter's DIP. I mean the example shouldn't be set from they?
Feb 13
prev sibling next sibling parent Ron Tarrant <rontarrant gmail.com> writes:
On Thursday, 13 February 2020 at 07:29:00 UTC, Mike Parker wrote:

 https://github.com/dlang/DIPs/blob/c0c1c9f9665e0bc1db611f4e93e793d64451f763/DIPs/DIP1031.md
If I understand correctly what this change means, I've already been using the 'new' way and didn't actually realize there was another way. So... I see no problems here.
Feb 13
prev sibling next sibling parent neikeq <ignalfonsore gmail.com> writes:
I'm against this change unless there's a good reason other than 
simplifying the language.

The brace-style struct initializers allow for beautiful code. 
This comment summarizes it well: 
https://github.com/dlang/DIPs/pull/169#issuecomment-532830320
Feb 13
prev sibling next sibling parent reply Mathias Lang <pro.mathias.lang gmail.com> writes:
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.
Feb 13
next sibling parent reply aliak <something something.com> writes:
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).
Feb 13
parent reply Mathias Lang <pro.mathias.lang gmail.com> writes:
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.
Feb 13
next sibling parent reply aliak <something something.com> writes:
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.
Feb 14
parent matheus <matheus gmail.com> writes:
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.
Feb 14
prev sibling parent Thomas Brix <brix brix-verden.dk> writes:
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;
Feb 14
prev sibling next sibling parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
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/c0c1c9f9665e0bc1db611f4e93e793d64451
763/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
Feb 14
next sibling parent 12345swordy <alexanderheistermann gmail.com> writes:
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)]);
Feb 14
prev sibling next sibling parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 2/14/20 9:46 AM, Steven Schveighoffer wrote:
 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?
Hm... a possible benefit that has not been discussed, brace-style initialization is only allowed during initialization, because there are no types involved in the initialization expression. But if we did the above, then the struct literal Foo(ber: (a: 42, b: 84)) would be allowed in any expression, since the types for each parameter are unambiguous. To recap: 1. We could make a struct literal syntax specifically for non-ctor structs that allows omission of types, since there are no overloads to worry about. 2. Such syntax would be valid wherever such a struct needs creation, including expressions. examples: struct S { int x; int y; } struct P // to demonstrate ambiguity { int y; int x; } struct NoCtor { S s; } struct Ctor { S s; this(S s) { this.s = s; } this(P s) { this.s = S(x: p.x, y: p.y); } } void foo(Ctor c); void foo(NoCtor nc); void main() { S s = S(x: 1, y: 2); // given by this DIP NoCtor nc = NoCtor(s: (x: 1, y: 2)); // also OK, not a function call NoCtor nc2 = NoCtor((1, 2)); // also OK, no names required once inside struct literal without ctor Ctor c = Ctor(s: (x: 1, y: 2)); // Error, would be ambiguous Ctor c = Ctor(s: S(x: 1, y: 2)); // Must supply full expression for ctor param foo(Ctor(s: P(x: 1, y: 2)); // OK foo(NoCtor(s: (x: 1, y: 2))); // OK, not a ctor function } Essentially POD types get an upgrade for their static initialization syntax to be allowed in expressions. -Steve
Feb 14
parent Steven Schveighoffer <schveiguy gmail.com> writes:
On 2/14/20 11:39 AM, Steven Schveighoffer wrote:
    this(P s) { this.s = S(x: p.x, y: p.y); }
ugh, didn't finish this edit. Should be: this(P s) { this.s = S(x: s.x, y: s.y); }
Feb 14
prev sibling next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 2/14/2020 6:46 AM, Steven Schveighoffer wrote:
 Now, imagine Vector2D and Moves are templated on type! Would be horrendous.
That's why D has alias declarations.
Feb 14
next sibling parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 2/14/20 4:49 PM, Walter Bright wrote:
 On 2/14/2020 6:46 AM, Steven Schveighoffer wrote:
 Now, imagine Vector2D and Moves are templated on type! Would be 
 horrendous.
That's why D has alias declarations.
An alias declaration is a declaration. It needs its own line before the expression use. This is unwieldy as well, further squirreling away the definition from the usage, requiring more lookup time. Promoting "just use an alias" means someone just "quickly" adds an alias to make the thing short: alias X = Vector2D!double; ... // some many lines later auto awsd = Moves!double(items: [X(x: 1, y: 0), X(x: 0, y: 1), X(x: -1, y: 0), X(x:0, y:-1)]); Leaving the reader scratching his head at where X comes from after looking up the Moves layout and not seeing it there. Even with the alias, repeating the type over and over is really an exercise in rote frustration. Especially when the compiler already knows how to figure this out without help (it already does this correctly with struct initializer syntax today). -Steve
Feb 14
next sibling parent IGotD- <nise nise.com> writes:
On Friday, 14 February 2020 at 22:11:36 UTC, Steven Schveighoffer 
wrote:
 An alias declaration is a declaration. It needs its own line 
 before the expression use. This is unwieldy as well, further 
 squirreling away the definition from the usage, requiring more 
 lookup time.

 Promoting "just use an alias" means someone just "quickly" adds 
 an alias to make the thing short:

 alias X = Vector2D!double;

 ... // some many lines later

 auto awsd = Moves!double(items: [X(x: 1, y: 0), X(x: 0, y: 1), 
 X(x: -1, y: 0), X(x:0, y:-1)]);

 Leaving the reader scratching his head at where X comes from 
 after looking up the Moves layout and not seeing it there. Even 
 with the alias, repeating the type over and over is really an 
 exercise in rote frustration.

 Especially when the compiler already knows how to figure this 
 out without help (it already does this correctly with struct 
 initializer syntax today).

 -Steve
Yes, typing in the type name quickly gets old for these kinds of use cases. I previously asked if writing (x: 1, y: 0) would be enough and the compiler would infer the type itself. With your example not even auto(x: 1, y: 0) would be sufficient. As I see it in order for this DIP to pass and retain the usability just as before the compiler must infer the type just like with curly brackets.
Feb 14
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 2/14/2020 2:11 PM, Steven Schveighoffer wrote:
 ... // some many lines later
It can be done inline with lambdas, like dmd itself does: https://github.com/dlang/dmd/blob/master/src/dmd/backend/oper.d#L387 and the lambdas can be arbitrarily complex. I wrote those bits to replace the optabgen.d program.
Feb 14
parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 2/14/20 6:44 PM, Walter Bright wrote:
 On 2/14/2020 2:11 PM, Steven Schveighoffer wrote:
 ... // some many lines later
It can be done inline with lambdas, like dmd itself does:   https://github.com/dlang/dmd/blob/master/src/dmd/backend/oper.d#L387 and the lambdas can be arbitrarily complex. I wrote those bits to replace the optabgen.d program.
Not sure what this is supposed to mean. I hope not: auto moves = Moves!double(items: [(){return Vector2d!double(x: 1, y: 0); }(), ...]) -Steve
Feb 15
parent Walter Bright <newshound2 digitalmars.com> writes:
On 2/15/2020 6:23 AM, Steven Schveighoffer wrote:
 Not sure what this is supposed to mean.
Generally, such things can get a lot clearer if you use better formatting rather than mushing it all into one line.
Feb 15
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 2/14/2020 1:49 PM, Walter Bright wrote:
 On 2/14/2020 6:46 AM, Steven Schveighoffer wrote:
 Now, imagine Vector2D and Moves are templated on type! Would be horrendous.
That's why D has alias declarations.
You can also do: auto v(float a, float b) { return Vector2D(x: a, y: b); } and: Moves awsd = {items: [{x: 1, y: 0}, {x: 0, y: 1}, {x: -1, y: 0}, {x:0, y:-1}]}; becomes: auto awsd = Moves(items: [v(1,0), v(0,1), v(-1,0), v(0,-1)]); voila!
Feb 14
next sibling parent Steven Schveighoffer <schveiguy gmail.com> writes:
On 2/14/20 6:10 PM, Walter Bright wrote:
 On 2/14/2020 1:49 PM, Walter Bright wrote:
 On 2/14/2020 6:46 AM, Steven Schveighoffer wrote:
 Now, imagine Vector2D and Moves are templated on type! Would be 
 horrendous.
That's why D has alias declarations.
You can also do:     auto v(float a, float b) { return Vector2D(x: a, y: b); } and:    Moves awsd = {items: [{x: 1, y: 0}, {x: 0, y: 1}, {x: -1, y: 0}, {x:0, y:-1}]}; becomes:     auto awsd = Moves(items: [v(1,0), v(0,1), v(-1,0), v(0,-1)]); voila!
This is less attractive than the alias, because now I'm calling a function for all the items (and I still need an extra declaration somewhere). Not only that, but you modified the parameter names, so now it's a and b instead of x and y. And finally, you removed the documentation of what members the call is setting (the 'x' and 'y'). Still not as good IMO as the original call with brace style initialization, which needs no extra framework definitions, and no reason to search the code space for the "v" function to understand what it is doing. So far, this looks like a step backwards in code clarity, efficiency, and beauty. -Steve
Feb 14
prev sibling parent NX <nightmarex1337 hotmail.com> writes:
The following code is from actual real world:

VkPipelineViewportStateCreateInfo viewportStateInfo = {
	viewportCount : 1,
	pViewports    : [ {0f, 0f, 1920f, 1080f, -1f, 1f} ],
	scissorCount  : 1,
	pScissors     : [ {{0, 0}, {1920, 1080}} ],
};

If the brace-style struct initializers get deprecated this is 
what I have to write:

auto viewportStateInfo = VkPipelineViewportStateCreateInfo(
	viewportCount : 1,
	pViewports    : [ VkViewport(0f, 0f, 1920f, 1080f, -1f, 1f) ],
	scissorCount  : 1,
	pScissors     : [ VkRect2D(VkOffset2D(0, 0), VkExtent2D(1920, 
1080))) ],
);

The following is what it looks like if I use parameter names as 
well, and it's not hard to imagine having to write code like this 
if someone has complicated nested structures:

auto viewportStateInfo = VkPipelineViewportStateCreateInfo(
	viewportCount : 1,
	pViewports    : [ VkViewport(x:0f, y:0f, width:1920f, 
height:1080f, minDepth:-1f, maxDepth:1f) ],
	scissorCount  : 1,
	pScissors     : [ VkRect2D(offset: VkOffset2D(x:0, y:0), extent: 
VkExtent2D(width:1920, height:1080))) ],
);


Absolutely not ideal. Doesn't scale. Too verbose.
This feature should be improved instead of making it deprecated. 
I've never seen someone getting confused by brace-style syntax. I 
have also yet to discover any deal breaking issues about this 
feature, and it doesn't seem complicated to support **at all**.
This would also break a good amount code and that is rather hard 
to automate by conventional text editing tools. (if only people 
cared about dfix huh...)

Besides, I don't want my D code to look like java. I've had 
enough of that.
Feb 17
prev sibling next sibling parent aliak <something something.com> writes:
On Friday, 14 February 2020 at 14:46:43 UTC, Steven Schveighoffer 
wrote:
 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.
I really like that. I just got a glimpse of Andre's issue [0] and deprecating brace initialization really is going to put a big blotch on that code of his. And the workaround suggested looks really bad :( Especially considering the file is long, the number of AWS types are HUGE and having aliases like alias A = AnAwsType alias B = AnotherAwsType . . . /// Really not scalable... [0] https://github.com/dlang/DIPs/pull/169#issuecomment-532830320
Feb 14
prev sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2020-02-14 15:46, Steven Schveighoffer wrote:

 Foo f = Foo(ber: (a: 42, b: 84)); // only valid for struct 
(a: 42, b: 84) looks like a tuple with named elements to me. -- /Jacob Carlborg
Feb 15
parent Max Samukha <maxsamukha gmail.com> writes:
On Saturday, 15 February 2020 at 08:59:44 UTC, Jacob Carlborg 
wrote:
 On 2020-02-14 15:46, Steven Schveighoffer wrote:

 Foo f = Foo(ber: (a: 42, b: 84)); // only valid for struct
(a: 42, b: 84) looks like a tuple with named elements to me.
Exactly, a tuple-record hybrid. With Timon Gehr's tuple proposal + optionally named tuple elements + named parameters proposal, various forms of struct ctor invocation may become possible: Foo f = ((42, 84),) or Foo f = (ber: (a: 42, b: 84)) or auto f = Foo(ber: Bar(b: 84, a: 42)), etc.
Feb 15
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 2/13/2020 9:53 PM, Mathias Lang wrote:
 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);`.
auto f = Foo(42, 84); // no repetition
      This gets worse when a struct contains nested struct definitions, as
Andre 
 pointed out (here: https://github.com/dlang/DIPs/pull/169#issuecomment-532830320).
I replied to him there.
 --- 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.
For private structs like that, it's time to use an actual constructor. Frankly, allowing { } initializers for a private struct should be a bug, not a feature.
 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).
It's not a problem to stretch this out over time.
 This fits your own definition of "shuffling things around to no benefit".
Significantly simplifying the language is not shuffling.
Feb 14
parent reply jxel <jxel gmall.com> writes:
On Friday, 14 February 2020 at 21:35:10 UTC, Walter Bright wrote:
  On 2/13/2020 9:53 PM, Mathias Lang wrote:
 This fits your own definition of "shuffling things around to 
 no benefit".
Significantly simplifying the language is not shuffling.
Simplifying something isnt objectively better. Anyways, this is simplifying the language (by an insignificant margin) but greatly complicating large code that used this feature, that was being simplified as a result of the feature.
Feb 14
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 2/14/2020 7:59 PM, jxel wrote:
 ... greatly complicating ...
I know that n.g. discussions have a tendency to defend to the death a single stone and forget the quarry, but come on.
Feb 14
next sibling parent jxel <jxel gmall.com> writes:
On Saturday, 15 February 2020 at 04:50:31 UTC, Walter Bright 
wrote:
 On 2/14/2020 7:59 PM, jxel wrote:
 ... greatly complicating ...
I know that n.g. discussions have a tendency to defend to the death a single stone and forget the quarry, but come on.
If you have a large amount of code with nesting, yes. This is a big step backwards. The justification is flimsy and this will break code. There's bigger fish to fry that will have a more meaningful impact and won't break even more code.
Feb 14
prev sibling parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 2/14/20 11:50 PM, Walter Bright wrote:
 On 2/14/2020 7:59 PM, jxel wrote:
 ... greatly complicating ...
I know that n.g. discussions have a tendency to defend to the death a single stone and forget the quarry, but come on.
From the perspective of the user, the complications in the compiler or library are of zero significance. They care about what they have to write to get what they want, and how that code performs. In other words, they are not even in the quarry, but in the processing plant (or whatever you call the place the stones go after they are harvested). -Steve
Feb 15
next sibling parent reply rikki cattermole <rikki cattermole.co.nz> writes:
On 16/02/2020 3:39 AM, Steven Schveighoffer wrote:
 On 2/14/20 11:50 PM, Walter Bright wrote:
 On 2/14/2020 7:59 PM, jxel wrote:
 ... greatly complicating ...
I know that n.g. discussions have a tendency to defend to the death a single stone and forget the quarry, but come on.
From the perspective of the user, the complications in the compiler or library are of zero significance. They care about what they have to write to get what they want, and how that code performs. In other words, they are not even in the quarry, but in the processing plant (or whatever you call the place the stones go after they are harvested). -Steve
Except when the compiler ICE's out, they certainly care then. Compiler errors are to be expected when you don't have a full time team working on a compilers internal. From Walter's perspective it makes sense to want to limit the surface area of potential new bugs when you don't have the support to back you up. You can talk about quarries and processing plants but either the customer gets the exact product they want in the time that they have paid for or they don't. If we genuinely cared about the user, we should be doing HCI studies and doing formal proving of language constructs. But we don't. We cut corners because we have no choice to do so as it is too costly. The best way to resolve this situation from what I've seen is to heed off as many different perspectives in the DIP and have the DIP author chime in to expand on the discussion as soon as reasonably possible. This is something Walter could improve on.
Feb 15
next sibling parent Steven Schveighoffer <schveiguy gmail.com> writes:
On 2/15/20 10:03 AM, rikki cattermole wrote:
 On 16/02/2020 3:39 AM, Steven Schveighoffer wrote:
 On 2/14/20 11:50 PM, Walter Bright wrote:
 On 2/14/2020 7:59 PM, jxel wrote:
 ... greatly complicating ...
I know that n.g. discussions have a tendency to defend to the death a single stone and forget the quarry, but come on.
 From the perspective of the user, the complications in the compiler or library are of zero significance. They care about what they have to write to get what they want, and how that code performs. In other words, they are not even in the quarry, but in the processing plant (or whatever you call the place the stones go after they are harvested).
Except when the compiler ICE's out, they certainly care then.
Sure, but it doesn't. brace-initializers have been in the language from the beginning and they are a proven feature.
 Compiler errors are to be expected when you don't have a full time team 
 working on a compilers internal.
In general having the compiler simpler means an easier-to-maintain compiler. But simplifying the language to remove already working and proven features isn't progress. Unless you give them a new feature that replaces it (which could happen, if we wanted it to).
 You can talk about quarries and processing plants but either the 
 customer gets the exact product they want in the time that they have 
 paid for or they don't.
I think we are saying the same thing. The user only cares if it works, not how hard it was to implement. If it works as expected, and is bug free (it currently is), then to the user, removing it means losing the feature. It doesn't mean a less buggy compiler. It the brace initializers were riddled with bugs or design issues, then I can see a benefit for users. This isn't the case. Removing features has to have a better story than simplification of language. We could simplify foreach and for loops into just while loops. The language would be simpler and less surface area for mistakes. But the users would be not very happy about such a change. -Steve
Feb 15
prev sibling parent reply jxel <jxel gmall.com> writes:
On Saturday, 15 February 2020 at 15:03:56 UTC, rikki cattermole 
wrote:
 From Walter's perspective it makes sense to want to limit the 
 surface area of potential new bugs when you don't have the 
 support to back you up.
OK now let's not get too carried away. If that was even something Walter was considering he wouldn't be maintaining his own backend. I've come across a few code gen bugs, and they aren't fun to diagnose and fix especially with how poor quality the backend code is. Some 20 years of legacy ported from C over those years.
Feb 15
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 2/15/2020 9:58 AM, jxel wrote:
 how poor quality the backend code is.
Baloney. It's written in an older style, sure, but it's remarkably bug free considering how complex it is. The complexity is a result of the fiendishly complex x86 instructions set. The proof of its quality is it has successfully been extended from a purely 16 bit generator to 32 and extended again to 64 bit, and has been extended to support multiple ABIs and object file formats. The DFA optimizer has also proven to be fast and very robust.
Feb 15
parent reply jxel <jxel gmall.com> writes:
On Saturday, 15 February 2020 at 23:59:39 UTC, Walter Bright 
wrote:
 On 2/15/2020 9:58 AM, jxel wrote:
 how poor quality the backend code is.
Baloney.
No thank you, I don't eat baloney.
 It's written in an older style, sure, but it's remarkably bug 
 free considering how complex it is. The complexity is a result 
 of the fiendishly complex x86 instructions set.
The x86 instruction set is complex, but it allows you to generate simpler assembly. The backend will never support ARM because its a simpler instruction set and architecture that leans heavily on the codegen/optimizer producing correct assembly.
 The proof of its quality is it has successfully been extended 
 from a purely 16 bit generator to 32 and extended again to 64 
 bit, and has been extended to support multiple ABIs and object 
 file formats.
What you've just described is a symptom that leads to poor quality code. Some sort of Frankenstein that has to be mcgyvered into doing something it originally wasn't designed to do.
Feb 15
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 2/15/2020 5:23 PM, jxel wrote:
 The backend will never support ARM because its a simpler instruction set
There actually was one for the ARM. It wasn't completed because the person writing it ran out of steam, not because he hit architectural dead ends. Besides, the idea that an architecture designed to support a kludgy instruction set can't support a regular one doesn't make much sense.
 What you've just described is a symptom that leads to poor quality code. Some 
sort of Frankenstein that has to be mcgyvered into doing something it originally wasn't designed to do. BTW, it was also extended to support the SIMD instruction set, which is architecturally fairly different. It was extended as well to support x87, which is architecturally rather unique. I'm amused that a hallmark of poor quality is being adaptable to diverse architectures. No other backend has ever been able to come close to its speed at the level of code quality it produces (it was originally designed to run on 16 bit floppy systems). But I'm open to suggestions for improvement of the quality. If you have something specific, PRs are welcome.
Feb 15
next sibling parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Sat, Feb 15, 2020 at 09:13:01PM -0800, Walter Bright via Digitalmars-d wrote:
[...]
 I'm amused that a hallmark of poor quality is being adaptable to
 diverse architectures.
Yeah, I think the original criticism here was a bit ridiculous. However:
 No other backend has ever been able to come close to its speed at the
 level of code quality it produces (it was originally designed to run
 on 16 bit floppy systems).
What's the point of lightning fast generation of poor quality code? Okay, during development it's good to have fast turnaround times. But what when it's release time and I want to squeeze the last bit of juice from the generated code? Running dmd -O for this is, sorry to say, a disappointment. I've measured this against LDC and GDC, and they *consistently* produce code that outperforms dmd-generated code. A 20%/30% speedup is typical, sometimes with compute-heavy code it can be 40% faster than dmd generated code. I've been saying this for years, and even reported bugs about it. But so far, things have not changed very much. When runtime performance matters, I don't even consider dmd, I already know ldc/gdc will produce faster code. So sure, the dmd backend is the fastest of its kind that produces 20% slower code, but that's hardly something to boast about now, is it?
 But I'm open to suggestions for improvement of the quality. If you
 have something specific, PRs are welcome.
Well this is part of the problem: because the code style is old and unfamiliar to most contemporary programmers, you're not going to find many people who would be able to contribute a PR. And those who can may not necessarily be willing to spend the time to do so. Chicken and egg problem. People *can* file bugs related to performance, though. I did. And I'm still waiting for results. T -- One reason that few people are aware there are programs running the internet is that they never crash in any significant way: the free software underlying the internet is reliable to the point of invisibility. -- Glyn Moody, from the article "Giving it all away"
Feb 15
next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 2/15/2020 10:27 PM, H. S. Teoh wrote:
 What's the point of lightning fast generation of poor quality code?
The speed of the code generated was competitive with (and sometimes ahead of) the other compilers from 1985 to 2000 when I worked actively on it. It slowly fell behind after that as I was spending my time on the D front end. This is not evidence that the code quality of the back end is poor.
 Well this is part of the problem: because the code style is old and
 unfamiliar to most contemporary programmers, you're not going to find
 many people who would be able to contribute a PR. And those who can may
 not necessarily be willing to spend the time to do so.  Chicken and egg
 problem.
There are very, very few programmers out there who understand code generation issues well enough to improve things. It has nothing to do with the back end being old fashioned. The data structures in it are simple and straightforward. That said, some people have contributed some good work to the back end, but nothing fundamental.
Feb 16
parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Sun, Feb 16, 2020 at 12:18:30PM -0800, Walter Bright via Digitalmars-d wrote:
 On 2/15/2020 10:27 PM, H. S. Teoh wrote:
 What's the point of lightning fast generation of poor quality code?
The speed of the code generated was competitive with (and sometimes ahead of) the other compilers from 1985 to 2000 when I worked actively on it. It slowly fell behind after that as I was spending my time on the D front end. This is not evidence that the code quality of the back end is poor.
Note that I did not say the code quality of the back end is poor. I said that the quality of the code *generated* by the back end is poor. And that's not in an absolute sense, since obviously it's still of the same quality as it was back in 2000, but it's poor in the relative sense, compared to the output of modern backends like GDC or LDC. The problem is that while the rest of the world has marched on since 2000, the DMD backend has remained stagnant. Effectively, therefore, it's regressing -- not in the absolute sense of course, but relative to the rest of the world that has since moved on. Which means that now it's a much harder sell to choose the DMD backend over, say, LDC or GDC's. As a user, I don't care how good the DMD backend is as long as its output is inferior compared to alternative backends; obviously I'm going to choose the backend that gives me better generated code, regardless of how either backend arrives at it. Maybe the GDC backend is garbage in terms of its own code quality (as an example -- I don't know the GDC backend code), but as long as the code it *generates* performs faster than the code DMD generates, users are going to choose it over DMD.
 Well this is part of the problem: because the code style is old and
 unfamiliar to most contemporary programmers, you're not going to
 find many people who would be able to contribute a PR. And those who
 can may not necessarily be willing to spend the time to do so.
 Chicken and egg problem.
There are very, very few programmers out there who understand code generation issues well enough to improve things. It has nothing to do with the back end being old fashioned. The data structures in it are simple and straightforward. That said, some people have contributed some good work to the back end, but nothing fundamental.
And that is precisely the problem. While GDC/LDC backends may or may not have the technical superiority over DMD's backend, what matters is that people are improving it over time, whereas the DMD backend has been staying stagnant. It doesn't matter what the reason is -- maybe programmers are not competent enough to work on the DMD backend, maybe there's some other reason, but what matters is that there are very few people actively improving the DMD backend, whereas there are large teams of people honing the GDC/LDC backends continually. Effectively, therefore, the DMD backend is regressing, not in the sense that it's actually *degrading*, but in the sense that it's lagging behind the other backends. No matter how technically superior the DMD code may be, and no matter how inferior the other backends may be, what the user is going to choose will be decided by what kind of code is generated, not by what kind of code the backend is running. The DMD backend can be superior all it wants, but if the code it generates is slower than the code produced by GDC or LDC, then there is really no reason for me to prefer DMD over GDC or LDC. Therein lies the rub. T -- Why are you blatanly misspelling "blatant"? -- Branden Robinson
Feb 16
prev sibling parent bachmeier <no spam.net> writes:
On Sunday, 16 February 2020 at 06:27:32 UTC, H. S. Teoh wrote:
 What's the point of lightning fast generation of poor quality 
 code? Okay, during development it's good to have fast 
 turnaround times. But what when it's release time and I want to 
 squeeze the last bit of juice from the generated code?
I don't know about you, but I spend like 99.9% of my time in the development phase and 0.1% in the final release build phase. In a lot of cases DMD produces code that's more than good enough, so I don't even both with LDC, but it really doesn't add anything to my development time to add a final call to LDC. If you could alias DMD -O to call LDC, you wouldn't notice the difference.
Feb 17
prev sibling parent jxel <jxel gmall.com> writes:
On Sunday, 16 February 2020 at 05:13:01 UTC, Walter Bright wrote:
 PRs are welcome.
They really aren't. Every time there's some sort of significant change of a pull request, you shut it down as 'reshuffling'. It's also not my job to cleanup. There's a perfectly fine D compiler with a quality backend known as LDC. The only pull request I'd make would be to merge LDC in.
Feb 16
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 2/15/2020 6:39 AM, Steven Schveighoffer wrote:
  From the perspective of the user, the complications in the compiler or
library 
 are of zero significance.
The complication is in the language. This affects the user: 1. the language is larger 2. user has to decide "should I do it the A way or the B way?" 3. documentation is longer 4. anyone writing a book/tutorial on D has to become proficient with it 5. introduces bugs (such as the one just noticed that the { } allows access to private fields) It is not at all zero.
Feb 15
next sibling parent jxel <jxel gmall.com> writes:
On Saturday, 15 February 2020 at 23:54:17 UTC, Walter Bright 
wrote:
 On 2/15/2020 6:39 AM, Steven Schveighoffer wrote:
  From the perspective of the user, the complications in the 
 compiler or library are of zero significance.
The complication is in the language. This affects the user: 1. the language is larger 2. user has to decide "should I do it the A way or the B way?" 3. documentation is longer 4. anyone writing a book/tutorial on D has to become proficient with it 5. introduces bugs (such as the one just noticed that the { } allows access to private fields) It is not at all zero.
You could remove quite a few features, and prevent new ones for those reasons. Named parameters to start, especially with the current DIP that just introduces complexity for very little benefit and increases the burden on library authors to maintain compatibility. The new live attribute, that's going to add way more complexity. The "in" and "out" qualifiers aren't really needed, and kind of useless and redundant. The ?: operator, don't really need it, just use a normal if statement. The "const" qualifier could be removed and nothing of significance would be lost, no body uses it anyway. Interpolated strings as well, its just syntactic sugar. The in and out contracts, there's a bunch of bugs with those and really just having asserts in the body of the function provides basically the same functionality. I don't really see anyone using that feature. I'm sure I could go on with some more. Deprecate 'real', it should be a 128 bit float, no body uses 80 bit floats and just having it be the largest possible dp unit is just repeating c's mistakes. Anyways for sure now, there's probably more features that you could remove for the same rationale you are giving as this one. D has numerous issues with not following private. Its cause its not something that someone pays attention to. I forget if allMembers was updated to not all private access.or to allow it, either way its not just this one feature that breaks private.
Feb 15
prev sibling parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 2/15/20 6:54 PM, Walter Bright wrote:
 On 2/15/2020 6:39 AM, Steven Schveighoffer wrote:
  From the perspective of the user, the complications in the compiler 
 or library are of zero significance.
The complication is in the language. This affects the user: 1. the language is larger 2. user has to decide "should I do it the A way or the B way?" 3. documentation is longer
All these points apply to for loops and foreach loops as well. All of these can be done with while loops. Yet, we don't want to remove them because they provide a good readable syntax for what is required in most cases. In my opinion, when you are adding features, you have a different bar to cross than when you are removing them. If adding, does the feature provide enough benefit syntactically over existing mechanisms to justify a language change. If removing, is there an alternate feature that can mimic it to a sufficient degree that we can remove it with a straightforward positive conversion? Look at octals and hex strings. Both of these were implemented via a library call that provided equivalent operation. The syntax sugar was gone, but octals were confusing and error prone in their current state (being more verbose there with an `octal!` was a benefit), and hex strings simply weren't worth an entire language feature for it when CTFE could do exactly the same thing with a single call (newCTFE will help here too). In this DIP, we are exploding the verbosity and repetitiveness to an uncomfortable degree, which frankly wasn't even necessary before. The brace syntax is beautifully minimal. If we can alleviate that concern, I think there would be no problem to remove this feature.
 4. anyone writing a book/tutorial on D has to become proficient with it
Really? You have to be proficient in D struct initializers to write a book? I'm pretty sure I have at least 2 D books without this in it. I actually don't ever use braced struct initializers. But the use cases that have been provided are pretty compelling, and your workarounds have not been. At least not enough to remove the syntax sugar provided without a comparable replacement.
 5. introduces bugs (such as the one just noticed that the { } allows 
 access to private fields)
Is that really a bug? Struct literals have this access as well. I'll also note that Mathias' example was not a private data member, but a private type (i.e. Voldemort type) with public members. His point was that everything being initialized was public, except the name. Which the new syntax requires whereas the old does not. .tupleof provides private access also. I think there are many libraries that probably depend on this, so you may want to deprecate that slowly. -Steve
Feb 15
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 2/15/2020 7:20 PM, Steven Schveighoffer wrote:
 All these points apply to for loops and foreach loops as well. All of these
can 
 be done with while loops.
It's the while loop that is redundant. foreach is key to writing generic code that would be impractical using for loops for.
 Yet, we don't want to remove them because they provide a good readable syntax 
 for what is required in most cases.
That's not really why. I can explain more if you like.
 In this DIP, we are exploding the verbosity and repetitiveness to an 
 uncomfortable degree, which frankly wasn't even necessary before. The brace 
 syntax is beautifully minimal.
You said you don't use this syntax. I've used it since the beginning. I wouldn't miss it. Left unsaid in all this is the static initializer syntax can only be use for statics, and even then only for structs without a constructor. I've never heard a complaint about how terrible it was to use the function-style syntax, which is required for every other use. As for using Voldemort types in a static initializer, good luck contriving a use case for that. And if one manages to do it, there's still a usable workaround - typeof - which Mathias used.
 4. anyone writing a book/tutorial on D has to become proficient with it
Really? You have to be proficient in D struct initializers to write a book? I'm pretty sure I have at least 2 D books without this in it.
Ali's book certainly does (Section 47.3). Andrei's does not, it uses the function style syntax. --- BTW, if you want to present a DIP for anonymous struct literals, please do so.
Feb 15
parent reply Paul Backus <snarwin gmail.com> writes:
On Sunday, 16 February 2020 at 05:57:22 UTC, Walter Bright wrote:
 Left unsaid in all this is the static initializer syntax can 
 only be use for statics, and even then only for structs without 
 a constructor.
It actually works for dynamic initialization too:
 The static initializer syntax can also be used to initialize 
 non-static variables. The initializer need not be evaluable at 
 compile time.
Source: https://dlang.org/spec/struct.html#dynamic_struct_init
Feb 15
parent Walter Bright <newshound2 digitalmars.com> writes:
On 2/15/2020 10:09 PM, Paul Backus wrote:
 On Sunday, 16 February 2020 at 05:57:22 UTC, Walter Bright wrote:
 Left unsaid in all this is the static initializer syntax can only be use for 
 statics, and even then only for structs without a constructor.
It actually works for dynamic initialization too:
 The static initializer syntax can also be used to initialize non-static 
 variables. The initializer need not be evaluable at compile time.
Source: https://dlang.org/spec/struct.html#dynamic_struct_init
Yes, you're right. My mistake.
Feb 17
prev sibling next sibling parent reply John Colvin <john.loughran.colvin gmail.com> writes:
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

 Here in the discussion thread, you are free to discuss anything 
 and everything related to the DIP. Express your support or 
 opposition, debate alternatives, argue the merits... in other 
 words, business as usual.

 However, if you have any specific feedback for how to improve 
 the the proposal itself, then please post it in the feedback 
 thread. The feedback thread will be the source for the review 
 summary I write at the end of this review round. I will post a 
 link to that thread immediately following this post. Just be 
 sure to read and understand the Reviewer Guidelines before 
 posting there:

 https://github.com/dlang/DIPs/blob/master/docs/guidelines-reviewers.md

 The review period will end at 11:59 PM ET on February 27, or 
 when I make a post declaring it complete. Discussion in this 
 thread may continue beyond that point.

 At the end of Round 1, if further review is deemed necessary, 
 the DIP will be scheduled for another round of Community 
 Review. Otherwise, it will be queued for the Final Review and 
 Formal Assessment.

 Please stay on topic here. I will delete posts that are 
 completely off topic.
:( I really like them and would prefer to have them do more. So currently I can write this: struct Q { int b; string c; } struct S { int a; Q q; } S s = { a: 3, q: { b: 5, c: "hello" } } and that's great. But what I'd really love to be able to do would be this: S foo() { return { a: 3, q: { b: 5, c: "hello" } }; } and Tuple!(int, "a", int, "b") bar() { return { x: 3, y: 7 }; } and even auto bar() { return { x: 3, y: 7 }; } static assert(is(typeof(bar()) == Tuple!(int, "x", int, "y"))); Although probably not lowering to the phobos std.typecons.Tuple for obvious reasons. Anonymous structures are great.
Feb 15
next sibling parent Aliak <something something.com> writes:
On Saturday, 15 February 2020 at 21:59:26 UTC, John Colvin wrote:
 On Thursday, 13 February 2020 at 07:29:00 UTC, Mike Parker 
 wrote:
 [...]
:( I really like them and would prefer to have them do more. So currently I can write this: struct Q { int b; string c; } struct S { int a; Q q; } S s = { a: 3, q: { b: 5, c: "hello" } } and that's great. But what I'd really love to be able to do would be this: S foo() { return { a: 3, q: { b: 5, c: "hello" } }; } and Tuple!(int, "a", int, "b") bar() { return { x: 3, y: 7 }; } and even auto bar() { return { x: 3, y: 7 }; } static assert(is(typeof(bar()) == Tuple!(int, "x", int, "y"))); Although probably not lowering to the phobos std.typecons.Tuple for obvious reasons. Anonymous structures are great.
I know this statement is completely unconstuctive but 😍
Feb 15
prev sibling parent reply Mathias Lang <pro.mathias.lang gmail.com> writes:
On Saturday, 15 February 2020 at 21:59:26 UTC, John Colvin wrote:
 :(

 I really like them and would prefer to have them do more.

 [...]

 But what I'd really love to be able to do would be this:

 S foo()
 {
     return { a: 3, q: { b: 5, c: "hello" } };
 }

 and [...]
This (and the rest of the post) 100%. The only thing that ever annoyed me about struct literals is that they don't work everywhere.
Feb 16
parent Petar Kirov [ZombineDev] <petar.p.kirov gmail.com> writes:
On Sunday, 16 February 2020 at 15:24:26 UTC, Mathias Lang wrote:
 [..]

 The only thing that ever annoyed me about struct literals is 
 that they don't work everywhere.
I completely agree. I have several developers on my team with mostly JavaScript/TypeScript background, and it would be quite difficult to introduce D to them without the relatable (and also people for coming from C) struct literal syntax. These days is quite rare to find a JS/TS project that doesn't make a heavy use of this feature: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment https://javascript.info/destructuring-assignment If accepting the named parameters proposal meant that we could simply replace braces with parentheses, I'd onboard with DIP1031, but not before. (Of course that would involve a semantic change, as currently the brace literal syntax works only for initializing structs without constructors and named parameters are meant to invoke either the user defined constructor or the default synthesized one.)
Feb 17
prev sibling next sibling parent MoonlightSentinel <moonlightsentinel disroot.org> writes:
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":
Effectlively this DIP proposes simplifying the compiler - not so much the language itself - primarily because this feature is used seldomly and provides little value. But there are several problem which undermine this rationale. I would argue that this feature is one of the simpler features of for beginners to learn. You have a struct, enumerate it's field with appropriate values and get an initialized instance. This has compelling use cases (which Andre already presented) and were the alternatives are much more verbose. This is in conflict with one of D's core strengths, writing expressive and clean code. This leads to the question why this feature is rarely used. The current discussion mentions them being type system holes (because they circumvent constructors) [1] and their restriction to variable initializers [2]. I think we should address these issues to increase the usability of the current syntax instead of simply deprecating it. Suggestions: [1] Deprecate (and soon disallow) brace-style initializers for non-PODs [2] Allow brace-style initializers wherever a corresponding struct rvalue is allowed (and can be resolved unambiguously)
Feb 16
prev sibling parent reply Nathan S. <no.public.email example.com> writes:
Would removing support for brace-style struct initializers 
significantly simplify or speed up some portion of DMD?
Feb 16
parent Walter Bright <newshound2 digitalmars.com> writes:
On 2/16/2020 11:38 PM, Nathan S. wrote:
 Would removing support for brace-style struct initializers significantly 
 simplify or speed up some portion of DMD?
No.
Feb 17