www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Struct initialization has no effect or error?

reply Brett <Brett gmail.com> writes:
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;
Oct 02 2019
next sibling parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
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
Oct 02 2019
next sibling parent mipri <mipri minimaltype.com> writes:
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.
Oct 02 2019
prev sibling parent reply Brett <Brett gmail.com> writes:
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.
Oct 02 2019
parent reply mipri <mipri minimaltype.com> writes:
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: import std.stdio; struct X { int a; this(int x) { a = x * 2; } } void main() { auto test = X(22); writeln(test.a); } output: 44
Oct 02 2019
parent reply Mike Parker <aldacron gmail.com> writes:
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.
Oct 02 2019
parent Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
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
Oct 03 2019
prev sibling parent reply mipri <mipri minimaltype.com> writes:
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); }
Oct 02 2019
parent Andre Pany <andre s-e-a-p.de> writes:
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
Oct 02 2019