digitalmars.D - Nicer syntax for constructors
- Trailzz (31/31) Nov 18 2018 This situation happens *very* often in object oriented
- 12345swordy (3/34) Nov 18 2018 Have tried to use templates/string mixin for this? Don't rush to
- Trailzz (2/4) Nov 18 2018 how would you use templates/string mixin for this?
- Jacob Carlborg (21/26) Nov 18 2018 Something like this:
- Trailzz (2/9) Nov 18 2018 This is still very clunky and hard to understand.
- Timon Gehr (29/38) Nov 18 2018 ---
- Trailzz (2/37) Nov 18 2018 This is arguably more clunky than just lots of `this.foo = foo`.
- Timon Gehr (3/6) Nov 18 2018 ?
- Steven Schveighoffer (8/47) Nov 19 2018 Maybe you didn't notice that util module is written *once*, and then
- dayllenger (6/17) Nov 18 2018 It is not good when there is one parameter, you probably will
- aberba (11/21) Nov 20 2018 I'm not sure if you get it but to understand some D code, there's
- Neia Neutuladh (13/17) Nov 18 2018 Dart does this, for reference. Some random code I happened to have lying...
- Adam D. Ruppe (16/16) Nov 18 2018 class A {
- bauss (3/19) Nov 19 2018 The problem with your solution is if you just want a and b
- Adam D. Ruppe (6/8) Nov 19 2018 That's why I said you can slice tuples. Of course, slice needs
- FeepingCreature (4/35) Nov 18 2018 You can use my boilerplate library
- NoMoreBugs (19/22) Nov 19 2018 Well, let's step back a bit, from the so called 'code bloat', and
- Erik van Velzen (13/36) Nov 19 2018 TypeScript:
- NoMoreBugs (23/35) Nov 19 2018 Well, I do not 'know' either of Typescript or Kotlin - so my
- JN (3/6) Nov 24 2018 Personally I am a huge fan of this feature. Dart has it and I've
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (2/4) Dec 03 2018 TypeScript has it as well.
This situation happens *very* often in object oriented programming: ``` this(string a, int b, char c, float d, uint e, bool f) { this.a = a; this.b = b; this.c = c; this.d = d; this.e = e; this.f = f; } ``` It would save a lot of code bloat if there was a simpler syntax for this, perhaps something like this: ``` this(string this.a, int this.b, char this.c, float this.d, uint this.e, bool this.f) { } ``` It would be very easy to infer the types here, so this could also work ``` this(this.a, this.b, this.c, this.d, this.e, this.f) { } ``` I'm not sure exactly what the syntax would be like, but I just wanted to know what other people think about this. Would it be worth creating a DIP for this?
Nov 18 2018
On Sunday, 18 November 2018 at 19:09:16 UTC, Trailzz wrote:This situation happens *very* often in object oriented programming: ``` this(string a, int b, char c, float d, uint e, bool f) { this.a = a; this.b = b; this.c = c; this.d = d; this.e = e; this.f = f; } ``` It would save a lot of code bloat if there was a simpler syntax for this, perhaps something like this: ``` this(string this.a, int this.b, char this.c, float this.d, uint this.e, bool this.f) { } ``` It would be very easy to infer the types here, so this could also work ``` this(this.a, this.b, this.c, this.d, this.e, this.f) { } ``` I'm not sure exactly what the syntax would be like, but I just wanted to know what other people think about this. Would it be worth creating a DIP for this?Have tried to use templates/string mixin for this? Don't rush to a DIP yet, until you exhaust other options.
Nov 18 2018
On Sunday, 18 November 2018 at 19:25:09 UTC, 12345swordy wrote:Have tried to use templates/string mixin for this? Don't rush to a DIP yet, until you exhaust other options.how would you use templates/string mixin for this?
Nov 18 2018
On 2018-11-18 20:26, Trailzz wrote:On Sunday, 18 November 2018 at 19:25:09 UTC, 12345swordy wrote:Something like this: import std.traits : ParameterIdentifierTuple; class Foo { int a; int b; this(int a, int b) { static foreach (name ; ParameterIdentifierTuple!(__ctor)) __traits(getMember, this, name) = mixin(name); } } void main() { auto f = new Foo(2, 3); assert(f.a == 2); assert(f.b == 3); } -- /Jacob CarlborgHave tried to use templates/string mixin for this? Don't rush to a DIP yet, until you exhaust other options.how would you use templates/string mixin for this?
Nov 18 2018
On Sunday, 18 November 2018 at 19:47:26 UTC, Jacob Carlborg wrote:this(int a, int b) { static foreach (name ; ParameterIdentifierTuple!(__ctor)) __traits(getMember, this, name) = mixin(name); } }This is still very clunky and hard to understand.
Nov 18 2018
On 18.11.18 20:52, Trailzz wrote:On Sunday, 18 November 2018 at 19:47:26 UTC, Jacob Carlborg wrote:--- module util; enum assignFields=q{{ import std.traits; static foreach(x;ParameterIdentifierTuple!(__traits(parent,{}))) static if(__traits(hasMember, this, x)) __traits(getMember,this,x)=mixin(x); }}; --- --- module app; import util; class C{ string a; int b; char c; float d; uint e; bool f; this(string a, int b, char c, float d, uint e, bool f){ mixin(assignFields); } } void main(){ import std.stdio; writeln((new C("1",2,'3',4.0,5,true).tupleof)); } ---this(int a, int b) { static foreach (name ; ParameterIdentifierTuple!(__ctor)) __traits(getMember, this, name) = mixin(name); } }This is still very clunky and hard to understand.
Nov 18 2018
On Sunday, 18 November 2018 at 19:59:27 UTC, Timon Gehr wrote:On 18.11.18 20:52, Trailzz wrote:This is arguably more clunky than just lots of `this.foo = foo`.On Sunday, 18 November 2018 at 19:47:26 UTC, Jacob Carlborg wrote:--- module util; enum assignFields=q{{ import std.traits; static foreach(x;ParameterIdentifierTuple!(__traits(parent,{}))) static if(__traits(hasMember, this, x)) __traits(getMember,this,x)=mixin(x); }}; --- --- module app; import util; class C{ string a; int b; char c; float d; uint e; bool f; this(string a, int b, char c, float d, uint e, bool f){ mixin(assignFields); } } void main(){ import std.stdio; writeln((new C("1",2,'3',4.0,5,true).tupleof)); } ---[...]This is still very clunky and hard to understand.
Nov 18 2018
On 18.11.18 21:06, Trailzz wrote:... This is arguably more clunky than just lots of `this.foo = foo`.? Define clunky.
Nov 18 2018
On 11/18/18 3:06 PM, Trailzz wrote:On Sunday, 18 November 2018 at 19:59:27 UTC, Timon Gehr wrote:Maybe you didn't notice that util module is written *once*, and then imported where used. All you would have to do is the one `mixin(assignFields)` line in the places you wanted this boiler plate. To me, this is an elegant, simple solution, and IMO, actually nicer than any proposed language syntax changes (I find having to put `this` in front of all the parameter names just as clunky as doing the assignments). -SteveOn 18.11.18 20:52, Trailzz wrote:This is arguably more clunky than just lots of `this.foo = foo`.On Sunday, 18 November 2018 at 19:47:26 UTC, Jacob Carlborg wrote:--- module util; enum assignFields=q{{ import std.traits; static foreach(x;ParameterIdentifierTuple!(__traits(parent,{}))) static if(__traits(hasMember, this, x)) __traits(getMember,this,x)=mixin(x); }}; --- --- module app; import util; class C{ string a; int b; char c; float d; uint e; bool f; this(string a, int b, char c, float d, uint e, bool f){ mixin(assignFields); } } void main(){ import std.stdio; writeln((new C("1",2,'3',4.0,5,true).tupleof)); } ---[...]This is still very clunky and hard to understand.
Nov 19 2018
On Sunday, 18 November 2018 at 19:59:27 UTC, Timon Gehr wrote:class C{ string a; int b; char c; float d; uint e; bool f; this(string a, int b, char c, float d, uint e, bool f){ mixin(assignFields); } }It is not good when there is one parameter, you probably will write usual assignment for readability. In most of cases - 1 or 2 parameters - this solution improves nothing. On the other hand, members with _ or m_ in the name will force parameters to have the same names in the OP syntax.
Nov 18 2018
On Sunday, 18 November 2018 at 19:52:48 UTC, Trailzz wrote:On Sunday, 18 November 2018 at 19:47:26 UTC, Jacob Carlborg wrote:I'm not sure if you get it but to understand some D code, there's some amount of language features you need to know about first like mixins, stuff in std.traits and what they do... and CTFE...a few others too. Otherwise, D code might look very weird to you. But once you get it, you'll smile to D code for its modelling power. The combination of these features can be mentally tasking if you don't understand each of them. I'll recommend the "Programming in D" book if you haven't read it already (http://ddili.org/ders/d.en/index.html). "I can do anything! with D."this(int a, int b) { static foreach (name ; ParameterIdentifierTuple!(__ctor)) __traits(getMember, this, name) = mixin(name); } }This is still very clunky and hard to understand.
Nov 20 2018
On Sun, 18 Nov 2018 19:09:16 +0000, Trailzz wrote:It would be very easy to infer the types here, so this could also work ``` this(this.a, this.b, this.c, this.d, this.e, this.f) ```Dart does this, for reference. Some random code I happened to have lying around: class Stat { StatType type; ShipToValue shipToValue; Stat(this.type, this.shipToValue); } So does CoffeeScript: class Animal constructor: ( name) -> C++ has initializer lists, which are clunkier, and I think they avoid invoking a copy constructor or something.
Nov 18 2018
class A { int a; string b; float c; this(typeof(this.tupleof) args) { this.tupleof = args; } } auto a = new A(4, "foo", 1.5); Of course, that assumes none of the internal types are const, that complicates things, and it assumes you want to set them all at once. It also doesn't work quite right with inheritance, but you can make that work by combining the base class tuple if you want. Keep in mind you can also slice tuples if you want a subset of the members.
Nov 18 2018
On Sunday, 18 November 2018 at 20:20:50 UTC, Adam D. Ruppe wrote:class A { int a; string b; float c; this(typeof(this.tupleof) args) { this.tupleof = args; } } auto a = new A(4, "foo", 1.5); Of course, that assumes none of the internal types are const, that complicates things, and it assumes you want to set them all at once. It also doesn't work quite right with inheritance, but you can make that work by combining the base class tuple if you want. Keep in mind you can also slice tuples if you want a subset of the members.The problem with your solution is if you just want a and b assigned.
Nov 19 2018
On Monday, 19 November 2018 at 16:15:38 UTC, bauss wrote:The problem with your solution is if you just want a and b assigned.That's why I said you can slice tuples. Of course, slice needs them to be contiguous but still. Though tbh I think this whole thing is folly - for pod, use struct and things just work. If your class has a group of pod stuff... use a struct!
Nov 19 2018
On Sunday, 18 November 2018 at 19:09:16 UTC, Trailzz wrote:This situation happens *very* often in object oriented programming: ``` this(string a, int b, char c, float d, uint e, bool f) { this.a = a; this.b = b; this.c = c; this.d = d; this.e = e; this.f = f; } ``` It would save a lot of code bloat if there was a simpler syntax for this, perhaps something like this: ``` this(string this.a, int this.b, char this.c, float this.d, uint this.e, bool this.f) { } ``` It would be very easy to infer the types here, so this could also work ``` this(this.a, this.b, this.c, this.d, this.e, this.f) { } ``` I'm not sure exactly what the syntax would be like, but I just wanted to know what other people think about this. Would it be worth creating a DIP for this?You can use my boilerplate library https://code.dlang.org/packages/boilerplate to automatically generate constructors for pod classes. Just mixin(GenerateThis);
Nov 18 2018
On Sunday, 18 November 2018 at 19:09:16 UTC, Trailzz wrote:I'm not sure exactly what the syntax would be like, but I just wanted to know what other people think about this. Would it be worth creating a DIP for this?Well, let's step back a bit, from the so called 'code bloat', and have a look at the definition of a function: return-type function-name(parameter declarations, if any) { declarations statements } What you are suggesting, is, in order to save a few keystrokes, that D changes the definition of a function (or a constructor function in this case). No language that has functions allows you do initialize variables in the section where you declare your parameters - at least, no language that I am aware of. Lets not surprise newcomers to D, anymore than they are already going to be surprised. Its bad enough you can't have a private member within a module! Initializing variables in the parameter section of the function would be a step too far.
Nov 19 2018
On Monday, 19 November 2018 at 12:30:20 UTC, NoMoreBugs wrote:On Sunday, 18 November 2018 at 19:09:16 UTC, Trailzz wrote:TypeScript: class MyClass { constructor( readonly myValue: number, myArgument: number, ) {} } also Kotlin: class MyClass( val myValue: Int, myArgument: String ) {}I'm not sure exactly what the syntax would be like, but I just wanted to know what other people think about this. Would it be worth creating a DIP for this?Well, let's step back a bit, from the so called 'code bloat', and have a look at the definition of a function: return-type function-name(parameter declarations, if any) { declarations statements } What you are suggesting, is, in order to save a few keystrokes, that D changes the definition of a function (or a constructor function in this case). No language that has functions allows you do initialize variables in the section where you declare your parameters - at least, no language that I am aware of.Lets not surprise newcomers to D, anymore than they are already going to be surprised. Its bad enough you can't have a private member within a module! Initializing variables in the parameter section of the function would be a step too far.
Nov 19 2018
On Monday, 19 November 2018 at 21:36:32 UTC, Erik van Velzen wrote:TypeScript: class MyClass { constructor( readonly myValue: number, myArgument: number, ) {} } also Kotlin: class MyClass( val myValue: Int, myArgument: String ) {}Well, I do not 'know' either of Typescript or Kotlin - so my statement stands correct ;-) Of course, my argument is more about consistency, and less about how a particular language implements a constructor. Consistency makes code easier to write, easier to understand, and easier to maintain. Sadly, D, like many languages, lets you do the same things in any number of ways - which just places more burden on programmers. Go-lang has kinda addressed this issue.. It's also about modularity/encapsulation I guess. The function definition is really a definition of its parts, what those parts do, and how they work together to form the desired 'functionality'. Lets keep 'the parts' - please. ----- return-type function-name(parameter declarations, if any) { declarations statements } ----
Nov 19 2018
On Sunday, 18 November 2018 at 19:09:16 UTC, Trailzz wrote:I'm not sure exactly what the syntax would be like, but I just wanted to know what other people think about this. Would it be worth creating a DIP for this?Personally I am a huge fan of this feature. Dart has it and I've used it a lot.
Nov 24 2018
On Saturday, 24 November 2018 at 13:11:39 UTC, JN wrote:Personally I am a huge fan of this feature. Dart has it and I've used it a lot.TypeScript has it as well.
Dec 03 2018