shorter alternative of constructor with parameter

H. S. Teoh via Digitalmars-d digitalmars-d at puremagic.com
Mon Jun 23 09:44:04 PDT 2014


On Mon, Jun 23, 2014 at 11:30:22AM -0400, Steven Schveighoffer via Digitalmars-d wrote:
> On Sat, 21 Jun 2014 15:47:03 -0400, Jonathan M Davis via Digitalmars-d
> <digitalmars-d at puremagic.com> wrote:
> 
> >On Sat, 21 Jun 2014 18:50:21 +0000
> >Xinok via Digitalmars-d <digitalmars-d at puremagic.com> wrote:
> >
> >>On Saturday, 21 June 2014 at 17:17:57 UTC, Suliman wrote:
> >>> Dart and few others modern languages support short declaration
> >>> constructor with parameter:
> >>>
> >>> class Person {
> >>>   String name;
> >>>
> >>>   Person(String name) {
> >>>     this.name = name;
> >>>   }
> >>> }
> >>>
> >>> // Shorter alternative
> >>> class Person {
> >>>   String name;
> >>>
> >>>   // parameters prefixed by 'this.' will assign to
> >>>   // instance variables automatically
> >>>   Person(this.name);
> >>> }
> >>>
> >>> it's there any DIP for adding this future to D?
> >>
> >>I'd prefer that we didn't crowd the language with minor shortcuts
> >>like these, and save syntactic sugar for more useful features.
> >>Plus, it would be easy enough to make a string mixin which generates
> >>such boilerplate code.
> >
> >Agreed. This would just add more stuff to the language that people
> >would have to understand, and it really doesn't add much benefit.
> >It's just a slightly terser syntax - and one that doesn't fit in with
> >any other kind of function declarations in D to boot.
> 
> Yeah, I don't think we save much with this. A mixin should be able to
> assign all the names given in the parameters that you name the same
> way.
> 
> In fact, I bet one can write a boiler-plate string that works for ANY
> class, using __traits(allMembers), as long as your parameter names
> match the member names. Then you just mixin that string as the first
> thing in the ctor.
[...]

Here's a first stab at a working mixin that does this (uncomment the
pragma(msg,...) lines to see the generated code):

	string defaultCtor(T)()
		if (is(T == class))
	{
		enum isDataMember(T, string memb) =
			is(typeof(typeof(__traits(getMember, T, memb)).init));
	
		// Generate function signature
		string params, ctorBody;
		string delim = "";
		foreach (memb; __traits(derivedMembers, T))
		{
			static if (isDataMember!(T, memb))
			{
				alias argtype = typeof(__traits(getMember, T, memb));
				auto argname = "_" ~ memb;
				params ~= delim ~ argtype.stringof ~ " " ~ argname;
				delim = ", ";
	
				ctorBody ~= "    " ~ memb ~ " = " ~ argname ~ ";\n";
			}
		}
	
		return "this(" ~ params ~ ")\n{\n" ~ ctorBody ~ "}";
	}
	
	class C {
		string name;
		int age;
		bool registered;
	
		mixin(defaultCtor!(typeof(this)));
		//pragma(msg, defaultCtor!(typeof(this)));
	
		void myMethod() {}
	}
	
	class D {
		int x, y;
		string label;
	
		mixin(defaultCtor!(typeof(this)));
		//pragma(msg, defaultCtor!(typeof(this)));
	}
	
	void main() {
		auto c = new C("John Doe", 30, true); // oh yeah
		auto d = new D(10, 20, "Node 1"); // rock on! ;-)
	}


Currently, this mixin doesn't handle inheritance very well, but it
should be trivial to extend it to collect all superclass data members
and package them off into a super(...) call inside the generated ctor.

D rawckz.


T

-- 
Making non-nullable pointers is just plugging one hole in a cheese grater. -- Walter Bright


More information about the Digitalmars-d mailing list