www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Setting field of struct object

reply Joel <joelcnz gmail.com> writes:
I've been watching a video (YouTube - "Pipeline-oriented 
programming - Scott Wlaschin - NDC Porto 2023") with something 
like the following code. This only sets the first method call, so 
I'm wanting to know how to make this work, for the subsequent 
methods.

```d
import std;

struct Person {
     string name, email;
     ulong age;
     auto withName(string name) { this.name=name; return this; }
     auto withEmail(string email) { this.email=email; return this; 
}
     auto withAge(ulong age) { this.age=age; return this; }
}

void main() {
     Person p;
     p.withName("Tom").withEmail("joelcnz gmail.com").withAge(44);
     writeln(p);
}
```
Jan 22
next sibling parent reply Joel <joelcnz gmail.com> writes:
On Monday, 22 January 2024 at 08:27:36 UTC, Joel wrote:
 I've been watching a video (YouTube - "Pipeline-oriented 
 programming - Scott Wlaschin - NDC Porto 2023") with something 
 like the following code. This only sets the first method call, 
 so I'm wanting to know how to make this work, for the 
 subsequent methods.

 ```d
 import std;

 struct Person {
     string name, email;
     ulong age;
     auto withName(string name) { this.name=name; return this; }
     auto withEmail(string email) { this.email=email; return 
 this; }
     auto withAge(ulong age) { this.age=age; return this; }
 }

 void main() {
     Person p;
     
 p.withName("Tom").withEmail("joelcnz gmail.com").withAge(44);
     writeln(p);
 }
 ```
Jan 22
parent reply Danilo <codedan aol.com> writes:
On Monday, 22 January 2024 at 08:35:01 UTC, Joel wrote:
 I've lost interest in the video, looks like horrible syntax 

Nonetheless, this usually used with Objects (new class/struct instances), like so: ```d import std; struct Person { string name, email; ulong age; auto withName(string name) { this.name=name; return this; } auto withEmail(string email) { this.email=email; return this; } auto withAge(ulong age) { this.age=age; return this; } } void main() { auto p = (new Person).withName("Tom") .withEmail("joelcnz gmail.com") .withAge(44); writeln(p); } ``` If you convert it to a class, add an `static opCall` for initialization, and a toString() method, it's even nicer: ```d module app; import std; class Person { private string name, email; private ulong age; auto withName(string name) { this.name=name; return this; } auto withEmail(string email) { this.email=email; return this; } auto withAge(ulong age) { this.age=age; return this; } static Person opCall() => new Person(); override string toString() { return "Person{ name: "~name~", age: "~age.to!string~", email: "~email~" }"; } } void main() { auto p = Person() .withName("Tom") .withEmail("joelcnz gmail.com") .withAge(44); writeln(p); } ``` It's common OOP style in some frameworks.
Jan 22
parent Danilo <codedan aol.com> writes:
On Monday, 22 January 2024 at 08:54:21 UTC, Danilo wrote:
 It's common OOP style in some frameworks.
With latest D you can also just use named parameters: ```d import std; struct Person { /*private*/ string name, email; /*private*/ ulong age; } void main() { auto p = Person( name: "Tom", email: "joelcnz gmail.com", age: 44, ); writeln(p); } ```
Jan 22
prev sibling next sibling parent reply zjh <fqbqrr 163.com> writes:
On Monday, 22 January 2024 at 08:27:36 UTC, Joel wrote:

 ```d
 import std;

 struct Person {
     string name, email;
     ulong age;
     auto withName(string name) { this.name=name; return this; }
     auto withEmail(string email) { this.email=email; return 
 this; }
     auto withAge(ulong age) { this.age=age; return this; }
 }

 void main() {
     Person p;
     
 p.withName("Tom").withEmail("joelcnz gmail.com").withAge(44);
     writeln(p);
 }
 ```
VS:`C++` ```d struct Person { string name, email; ulong age; } Person a{"n","email",33}; ```
Jan 22
next sibling parent Joel <joelcnz gmail.com> writes:
On Monday, 22 January 2024 at 08:54:54 UTC, zjh wrote:
 On Monday, 22 January 2024 at 08:27:36 UTC, Joel wrote:

 ```d
 import std;

 struct Person {
     string name, email;
     ulong age;
     auto withName(string name) { this.name=name; return this; }
     auto withEmail(string email) { this.email=email; return 
 this; }
     auto withAge(ulong age) { this.age=age; return this; }
 }

 void main() {
     Person p;
     
 p.withName("Tom").withEmail("joelcnz gmail.com").withAge(44);
     writeln(p);
 }
 ```
VS:`C++` ```d struct Person { string name, email; ulong age; } Person a{"n","email",33}; ```
What about in D: auto a=Person(“n”, “email”, 33);
Jan 22
prev sibling next sibling parent Danilo <codedan aol.com> writes:
On Monday, 22 January 2024 at 08:54:54 UTC, zjh wrote:
 VS:`C++`

 ```d
 struct Person {
     string name, email;
     ulong age;
 }
 Person a{"n","email",33};
 ```
It's not much different in D. ;) ```d import std; struct Person { string name, email; ulong age; } void main() { auto p = Person("Tom", "joelcnz gmail.com", 44); writeln(p); } ```
Jan 22
prev sibling next sibling parent FeepingCreature <feepingcreature gmail.com> writes:
On Monday, 22 January 2024 at 08:54:54 UTC, zjh wrote:
 On Monday, 22 January 2024 at 08:27:36 UTC, Joel wrote:

 ```d
 import std;

 struct Person {
     string name, email;
     ulong age;
     auto withName(string name) { this.name=name; return this; }
     auto withEmail(string email) { this.email=email; return 
 this; }
     auto withAge(ulong age) { this.age=age; return this; }
 }

 void main() {
     Person p;
     
 p.withName("Tom").withEmail("joelcnz gmail.com").withAge(44);
     writeln(p);
 }
 ```
VS:`C++` ```d struct Person { string name, email; ulong age; } Person a{"n","email",33}; ```
D: ```d import std.stdio; struct Person { string name, email; ulong age; } void main() { Person p = Person(name: "n", email: "email", age: 33); writefln!"%s"(p); } ```
Jan 22
prev sibling parent reply zjh <fqbqrr 163.com> writes:
On Monday, 22 January 2024 at 08:54:54 UTC, zjh wrote:

 ```d
 struct Person {
     string name, email;
     ulong age;
 }
 Person a{"n","email",33};
 ```
C++ can achieve ultimate `simplicity` without violating `DRY`, And here, D violates the `DRY` principle! Moreover, as the `package level, module level, class level, member level`, D language violates integrity. Because D has no `class level` limit. These are all not `serious states`.
Jan 22
next sibling parent zjh <fqbqrr 163.com> writes:
On Monday, 22 January 2024 at 11:31:11 UTC, zjh wrote:
D language violates integrity.
 Because D has no `class level` limit.
 These are all not `serious states`.
It seems that D language is not `professional`.
Jan 22
prev sibling next sibling parent reply Bkoie <bkoie049 gmail.com> writes:
On Monday, 22 January 2024 at 11:31:11 UTC, zjh wrote:
 On Monday, 22 January 2024 at 08:54:54 UTC, zjh wrote:
 C++ can achieve ultimate `simplicity` without violating `DRY`,
 And here, D violates the `DRY` principle!
 Moreover, as the `package level, module level, class level, 
 member level`, D language violates integrity.
 Because D has no `class level` limit.
 These are all not `serious states`.
i think D module base system is fine wished some other lang had the same you can avoid circular import ref. dry? well he can easily turn that into a generic config static factory which its look like hes trying to do. D is totally different from C++ in D you usually you wont construct the struct directly use alias as.
Jan 22
parent reply zjh <fqbqrr 163.com> writes:
On Monday, 22 January 2024 at 15:14:32 UTC, Bkoie wrote:

 D is totally different from C++ in D you usually you wont 
 construct the struct directly use alias as.
Stop being `unconventional` and quickly copy their `good things`. Otherwise, the `development speed` of the D language is really `too slow`!
Jan 22
parent Bkoie <bkoie049 gmail.com> writes:
On Monday, 22 January 2024 at 15:49:30 UTC, zjh wrote:
 Stop being `unconventional` and quickly copy their `good 
 things`.
 Otherwise, the `development speed` of the D language is really 
 `too slow`!
i mean there some truth but all look at this way rust has new or default to construct python ? can lead to garbage d from alias as etc...
Jan 22
prev sibling next sibling parent reply ryuukk_ <ryuukk.dev gmail.com> writes:
On Monday, 22 January 2024 at 11:31:11 UTC, zjh wrote:
 On Monday, 22 January 2024 at 08:54:54 UTC, zjh wrote:

 ```d
 struct Person {
     string name, email;
     ulong age;
 }
 Person a{"n","email",33};
 ```
C++ can achieve ultimate `simplicity` without violating `DRY`, And here, D violates the `DRY` principle! Moreover, as the `package level, module level, class level, member level`, D language violates integrity. Because D has no `class level` limit. These are all not `serious states`.
I used to want this feature too, but i then got hit by a bug when i reordered the fields in the struct.. i don't want to deal with that stuff anymore But we now have named arguments, so this feature could be make use of it, it's similar with enums, perhaps one day this could be revived: https://github.com/dlang/DIPs/blob/e2ca557ab9d3e60305a37da0d5b58299e0a9de0e/DIPs/DIP1044.md There is even a working implementation: https://github.com/dlang/dmd/pull/14650
Jan 22
parent reply ryuukk_ <ryuukk.dev gmail.com> writes:
I should note that it only took me 1 project to never want to 
touch C++ again.. that must be telling something, either about 
the language, or me, or both lol
Jan 22
parent reply zjh <fqbqrr 163.com> writes:
On Monday, 22 January 2024 at 15:33:01 UTC, ryuukk_ wrote:
 it only took me 1 project to never want to touch C++ again..
D language used to have no `copy constructor`, isn't it now added in again? You have to admit the good aspects of `C++`. You should take a look at the `latest C++`. C++ has already learned many advantages of `D`, but D has not made `significant progress`! As a user, `C++` is really not much different from D, and even surpasses D `in many aspects`. `RAII `, `variable parameter` template, `coroutine, concept`, `value semantics`, very easy to understand. Moreover, the `inheritance` of C++ is very enjoyable to use in many aspects.
Jan 22
parent reply bachmeier <no spam.net> writes:
On Monday, 22 January 2024 at 15:45:45 UTC, zjh wrote:
 On Monday, 22 January 2024 at 15:33:01 UTC, ryuukk_ wrote:
 it only took me 1 project to never want to touch C++ again..
D language used to have no `copy constructor`, isn't it now added in again? You have to admit the good aspects of `C++`. You should take a look at the `latest C++`. C++ has already learned many advantages of `D`, but D has not made `significant progress`! As a user, `C++` is really not much different from D, and even surpasses D `in many aspects`. `RAII `, `variable parameter` template, `coroutine, concept`, `value semantics`, very easy to understand. Moreover, the `inheritance` of C++ is very enjoyable to use in many aspects.
Sounds like you should be using C++. Why are you here?
Jan 22
parent reply zjh <fqbqrr 163.com> writes:
On Monday, 22 January 2024 at 15:47:23 UTC, bachmeier wrote:
 Sounds like you should be using C++. Why are you here?
I spent `too much time` on D.
Jan 22
parent reply zjh <fqbqrr 163.com> writes:
On Monday, 22 January 2024 at 15:51:37 UTC, zjh wrote:
 I spent `too much time` on D.
And some of the inherent `drawbacks` of `C++` are too hateful.
Jan 22
parent bachmeier <no spam.net> writes:
On Monday, 22 January 2024 at 15:56:59 UTC, zjh wrote:
 On Monday, 22 January 2024 at 15:51:37 UTC, zjh wrote:
 I spent `too much time` on D.
And some of the inherent `drawbacks` of `C++` are too hateful.
It's a package deal. Everything in C++ is there because there were benefits when they added it, but those benefits came with downsides. D will end up in the same place if it emulates C++.
Jan 22
prev sibling parent reply Renato <renato athaydes.com> writes:
On Monday, 22 January 2024 at 11:31:11 UTC, zjh wrote:
 On Monday, 22 January 2024 at 08:54:54 UTC, zjh wrote:

 ```d
 struct Person {
     string name, email;
     ulong age;
 }
 Person a{"n","email",33};
 ```
C++ can achieve ultimate `simplicity` without violating `DRY`, And here, D violates the `DRY` principle! Moreover, as the `package level, module level, class level, member level`, D language violates integrity. Because D has no `class level` limit. These are all not `serious states`.
You know you can use struct literals in initializers, right? ```d import std.stdio; struct Person { string name, email; ulong age; } void main() { Person p = {name: "Joe", email: "joe example.com", age: 30}; writeln(p); } ```
Jan 25
parent zjh <fqbqrr 163.com> writes:
On Thursday, 25 January 2024 at 08:46:34 UTC, Renato wrote:



```d
void main() {
     Person p = { "Joe", "joe ab.com", 30};
     writeln(p);
}
```

I just tested it and it works. It's `great`!
Jan 25
prev sibling parent Anonymouse <zorael gmail.com> writes:
On Monday, 22 January 2024 at 08:27:36 UTC, Joel wrote:
 ```d
 import std;

 struct Person {
     string name, email;
     ulong age;
     auto withName(string name) { this.name=name; return this; }
     auto withEmail(string email) { this.email=email; return 
 this; }
     auto withAge(ulong age) { this.age=age; return this; }
 }

 void main() {
     Person p;
     
 p.withName("Tom").withEmail("joelcnz gmail.com").withAge(44);
     writeln(p);
 }
 ```
I had reason to need this to work a while ago and `opDispatch` came in very handy. I was able to cook up one that forwarded calls to other members in a struct, while returning `this` by ref, allowing for chaining calls. I use it with UDAs. (Scroll to the unit tests for examples.) ```d /++ Mixin template generating an `opDispatch` redirecting calls to members whose names match the passed variable string but with an underscore prepended. +/ mixin template UnderscoreOpDispatcher() { ref auto opDispatch(string var, T)(T value) { import std.traits : isArray, isAssociativeArray, isSomeString; enum realVar = '_' ~ var; alias V = typeof(mixin(realVar)); static if (isAssociativeArray!V) { // Doesn't work with AAs without library solutions } else static if (isArray!V && !isSomeString!V) { mixin(realVar) ~= value; } else { mixin(realVar) = value; } return this; } auto opDispatch(string var)() inout { enum realVar = '_' ~ var; return mixin(realVar); } } /// unittest { struct Foo { int _i; string _s; bool _b; string[] _add; alias wordList = _add; mixin UnderscoreOpDispatcher; } Foo f; f.i = 42; // f.opDispatch!"i"(42); f.s = "hello"; // f.opDispatch!"s"("hello"); f.b = true; // f.opDispatch!"b"(true); f.add("hello"); // f.opDispatch!"add"("hello"); f.add("world"); // f.opDispatch!"add"("world"); assert(f.i == 42); assert(f.s == "hello"); assert(f.b); assert(f.wordList == [ "hello", "world" ]); auto f2 = Foo() .i(9001) .s("world") .b(false) .add("hello") .add("world"); assert(f2.i == 9001); assert(f2.s == "world"); assert(!f2.b); assert(f2.wordList == [ "hello", "world" ]); } ``` You could trivially adapt it to use a `withName`, `withEmail` calling scheme instead of the underscore thing.
Feb 01