Thread overview
Struct initialization has no effect or error?
Oct 02, 2019
Brett
Oct 02, 2019
H. S. Teoh
Oct 02, 2019
mipri
Oct 03, 2019
Brett
Oct 03, 2019
mipri
Oct 03, 2019
Mike Parker
Oct 03, 2019
Jonathan M Davis
Oct 02, 2019
mipri
Oct 02, 2019
Andre Pany
October 02, 2019
struct X { int a; }

X[1] x;

x[0] = {3};

or

x[0] = {a:3};

fails;

Should the syntax not extend to the case of array assignment? This avoids a double copy.

X y = {3};

works fine.

So one has to do

x[0] = y;


October 02, 2019
On Wed, Oct 02, 2019 at 05:37:57PM +0000, Brett via Digitalmars-d-learn wrote:
> struct X { int a; }
> 
> X[1] x;
> 
> x[0] = {3};
> 
> or
> 
> x[0] = {a:3};
> 
> fails;

This works:

	x[0] = X(123);


> Should the syntax not extend to the case of array assignment?

Arguably it should. But it's mainly cosmetic, since the X(123) syntax works just fine. (It *is* an incongruity in D's syntax, though. It's not a big deal once you learn it, but it's a bit counterintuitive the first time you need to use it.)


> This avoids a double copy.
[...]

Which any modern optimizer would optimize away.


T

-- 
It is of the new things that men tire --- of fashions and proposals and improvements and change. It is the old things that startle and intoxicate. It is the old things that are young. -- G.K. Chesterton
October 02, 2019
On Wednesday, 2 October 2019 at 17:54:20 UTC, H. S. Teoh wrote:
> On Wed, Oct 02, 2019 at 05:37:57PM +0000, Brett via Digitalmars-d-learn wrote:
>> struct X { int a; }
>> 
>> X[1] x;
>> 
>> x[0] = {3};
>> 
>> or
>> 
>> x[0] = {a:3};
>> 
>> fails;
>
> This works:
>
> 	x[0] = X(123);
>

I'd knew I'd gotten the impression from somewhere that this was the
recommended way to initialize structs, but it took me a while to find
it.

Learning D:

  auto ms1 = MyStruct(10, 11);// struct literal
  MyStruct ms2 = {10, 11};    // C-style, not preferred
  MyStruct ms3 = {b:11, a:10};// Named initializers

  ..

  Struct literals are convenient for simple types ...
  but they only allow for direct initialization of member
  variables. If more complex initialization is required, struct
  constructors should be used.

And then the impression was probably just from every single example
using the first form.

https://dlang.org/spec/struct.html#static_struct_init doesn't say that
this is dispreferred in any way, nor does it emphasize that you can't
use initialization syntax to assign to an already initialized variable
(this is probably obvious to C types). But there are 'Best Practices'
notes elsewhere in the page. This section could have one of those, to
say to just use the constructors.

October 02, 2019
On Wednesday, 2 October 2019 at 17:37:57 UTC, Brett wrote:
> X y = {3};
>
> works fine.
>
> So one has to do
>
> x[0] = y;

You could initialize x all at once. Complete example:

  import std.stdio;

  struct Point {
      int x, y;

      string toString() {
          import std.format : format;

          return format("(%d, %d)", x, y);
      }
  }

  void main() {
      Point[2] ps = [{0,0}, {4,4}];
      foreach (p; ps) writeln(p);
  }

October 02, 2019
On Wednesday, 2 October 2019 at 18:35:39 UTC, mipri wrote:
> On Wednesday, 2 October 2019 at 17:37:57 UTC, Brett wrote:
>> X y = {3};
>>
>> works fine.
>>
>> So one has to do
>>
>> x[0] = y;
>
> You could initialize x all at once. Complete example:
>
>   import std.stdio;
>
>   struct Point {
>       int x, y;
>
>       string toString() {
>           import std.format : format;
>
>           return format("(%d, %d)", x, y);
>       }
>   }
>
>   void main() {
>       Point[2] ps = [{0,0}, {4,4}];
>       foreach (p; ps) writeln(p);
>   }

The brace style struct initializer will likely be deprecated. Please see here https://github.com/dlang/DIPs/pull/169

Kind regards
Andre
October 03, 2019
On Wednesday, 2 October 2019 at 17:54:20 UTC, H. S. Teoh wrote:
> On Wed, Oct 02, 2019 at 05:37:57PM +0000, Brett via Digitalmars-d-learn wrote:
>> struct X { int a; }
>> 
>> X[1] x;
>> 
>> x[0] = {3};
>> 
>> or
>> 
>> x[0] = {a:3};
>> 
>> fails;
>
> This works:
>
> 	x[0] = X(123);
>
>
>> Should the syntax not extend to the case of array assignment?
>
> Arguably it should. But it's mainly cosmetic, since the X(123) syntax works just fine. (It *is* an incongruity in D's syntax, though. It's not a big deal once you learn it, but it's a bit counterintuitive the first time you need to use it.)
>
>
>> This avoids a double copy.
> [...]
>
> Which any modern optimizer would optimize away.
>
>
> T

I was trying to avoid such things since X is quite long in name. Not a huge deal... and I do not like the syntax because it looks like a constructor call.
October 03, 2019
On Thursday, 3 October 2019 at 04:33:26 UTC, Brett wrote:
> I was trying to avoid such things since X is quite long in name. Not a huge deal... and I do not like the syntax because it looks like a constructor call.

It is a constructor call, though. You can define your own as well:

  #! /usr/bin/env rdmd
  import std.stdio;

  struct X {
      int a;

      this(int x) {
          a = x * 2;
      }
  }

  void main() {
      auto test = X(22);
      writeln(test.a);
  }

output: 44

October 03, 2019
On Thursday, 3 October 2019 at 04:57:44 UTC, mipri wrote:
> On Thursday, 3 October 2019 at 04:33:26 UTC, Brett wrote:
>> I was trying to avoid such things since X is quite long in name. Not a huge deal... and I do not like the syntax because it looks like a constructor call.
>
> It is a constructor call, though. You can define your own as well:


Technically it's a struct literal. It's only a constructor if you define one, in which case struct literals no longer work. E.g.,

struct Foo {
    int x;

    this(int a, int b) { x = a + b; }
}

Without the constructor, the literal Foo(10) would be valid, but with the constructor you'll get a compiler error.

October 03, 2019
On Wednesday, October 2, 2019 11:48:46 PM MDT Mike Parker via Digitalmars-d- learn wrote:
> On Thursday, 3 October 2019 at 04:57:44 UTC, mipri wrote:
> > On Thursday, 3 October 2019 at 04:33:26 UTC, Brett wrote:
> >> I was trying to avoid such things since X is quite long in name. Not a huge deal... and I do not like the syntax because it looks like a constructor call.
> >
> > It is a constructor call, though. You can define your own as
>
> > well:
> Technically it's a struct literal. It's only a constructor if you define one, in which case struct literals no longer work. E.g.,
>
> struct Foo {
>      int x;
>
>      this(int a, int b) { x = a + b; }
> }
>
> Without the constructor, the literal Foo(10) would be valid, but with the constructor you'll get a compiler error.

Yeah. Syntactically, there's no real distinction, but the compiler doesn't do something like generate a constructor for you, and unlike with a constructor, you won't necessarily get errors if you do something like use too few arguments. So, if you had

struct S
{
    int x;
}

auto s = S(42);

and then changed it to

struct S
{
    int x;
    int y;
}

auto s = S(42);

the code would continue to compile without complaint. And if you had something like

struct S
{
    string s;
    int i;
}

auto s = S("hello", 42);

struct S
{
    string s;
    int foo;
    int i;
}

auto s = S("hello", 42);

you end up initializing the wrong members. The same if had

struct S
{
    int x;
    int y;
}

auto s = S(12, 99);

and changed it to

struct S
{
    int y;
    int x;
}

auto s = S(12, 99);

The fact that struct literals exist basically forces you to declare constructors if you don't want to have to worry about breaking code by rearranging member variables.

Personally, I think that using struct literals is just begging for bugs in your code, so I never use them, and I always declare constructors. I wish that struct literals weren't a thing at all, but some folks clearly like them.

If using a struct literal with braces without providing the member names gets deprecated like apparently Walter wants to do, then maybe using the construction syntax for struct literals would be deprecated as well, which would at least improve the situation. struct literals with member names are still error-prone, but at least you then eliminate the bugs where you initialize the wrong members and instead just get the ones where new members end up with the default value whether it's appropriate or not.

- Jonathan M Davis