www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - "Named parameter builder" pattern for template parameters

reply "monarch_dodra" <monarchdodra gmail.com> writes:
I trust everyone here knows about the "builder" pattern
(http://en.wikipedia.org/wiki/Builder_pattern)? It can be very
useful when the number of (optional) arguments in a function
start to run rampant, and you know the user only wants to start
setting a subset of these.

D has phenomenal meta programming possibilities, and I see more
and more templates taking more and more parameters. So I thought
to myself, why not have a template builder pattern?

I was able to throw this together:
http://dpaste.dzfl.pl/366d1fc22c9c

Which allows things like:
	alias MyContainerType = ContainerBuilder!int
		//.setUseGC!??? //Don't care about GCm use default.
		.setScan!false
		.setUSomeOtherThing!true
		.Type;

I think this is hugely neat. I'm posting here both to share, and
for "peer review feedback".

I'm also wondering if there is prior "literature" about this, and
if it's something we'd want more of in Phobos?
Nov 21 2014
next sibling parent reply ketmar via Digitalmars-d <digitalmars-d puremagic.com> writes:
On Fri, 21 Nov 2014 13:39:42 +0000
monarch_dodra via Digitalmars-d <digitalmars-d puremagic.com> wrote:

 D has phenomenal meta programming possibilities, and I see more
 and more templates taking more and more parameters. So I thought
 to myself, why not have a template builder pattern?
i did something similar in my iv.writer (ctfe format string parser). once i got about ten argumnets to each template (and growing), i moved everything to structure. struct WrData { ... fields ... auto set(string name, T) (in T value) if (__traits(hasMember, this, name)) { __traits(getMember, this, name) =3D value; return this; } } and then i can pass the struct around, changing only the fields i want, in "pseudo-functional" style: template MyTpl!(WrData data) { ... MyTpl!(data.set!"field0"(value0).set!"field1"(value1)); } that was a real saver. but now i have to wait for GDC update, 'cause 2.065 frontend is not able to use structs as template args.
Nov 21 2014
parent "monarch_dodra" <monarchdodra gmail.com> writes:
On Friday, 21 November 2014 at 14:46:00 UTC, ketmar via
Digitalmars-d wrote:
 On Fri, 21 Nov 2014 13:39:42 +0000
 monarch_dodra via Digitalmars-d <digitalmars-d puremagic.com> 
 wrote:

 D has phenomenal meta programming possibilities, and I see more
 and more templates taking more and more parameters. So I 
 thought
 to myself, why not have a template builder pattern?
i did something similar in my iv.writer (ctfe format string parser). once i got about ten argumnets to each template (and growing), i moved everything to structure. struct WrData { ... fields ... auto set(string name, T) (in T value) if (__traits(hasMember, this, name)) { __traits(getMember, this, name) = value; return this; } } and then i can pass the struct around, changing only the fields i want, in "pseudo-functional" style: template MyTpl!(WrData data) { ... MyTpl!(data.set!"field0"(value0).set!"field1"(value1)); } that was a real saver. but now i have to wait for GDC update, 'cause 2.065 frontend is not able to use structs as template args.
Hum, use a standard structure combined with CTFE to achieve the same goal. Smart. BTW, if you use opDispatch, you could probably have it as: MyTpl!(data.set_field0(value0).set_field1(value1)); Which may or may not read nicer, depending on how you look at it. With proper template overloading, you should even be able to implement this as a backwards compatible template.
Nov 21 2014
prev sibling next sibling parent "John Colvin" <john.loughran.colvin gmail.com> writes:
On Friday, 21 November 2014 at 13:39:43 UTC, monarch_dodra wrote:
 I trust everyone here knows about the "builder" pattern
 (http://en.wikipedia.org/wiki/Builder_pattern)? It can be very
 useful when the number of (optional) arguments in a function
 start to run rampant, and you know the user only wants to start
 setting a subset of these.

 D has phenomenal meta programming possibilities, and I see more
 and more templates taking more and more parameters. So I thought
 to myself, why not have a template builder pattern?

 I was able to throw this together:
 http://dpaste.dzfl.pl/366d1fc22c9c

 Which allows things like:
 	alias MyContainerType = ContainerBuilder!int
 		//.setUseGC!??? //Don't care about GCm use default.
 		.setScan!false
 		.setUSomeOtherThing!true
 		.Type;

 I think this is hugely neat. I'm posting here both to share, and
 for "peer review feedback".

 I'm also wondering if there is prior "literature" about this, 
 and
 if it's something we'd want more of in Phobos?
That's pretty awesome. There have been several times where I've been put off adding template parameters when I really wanted to, simply because I didn't want to have long, hard-to-read parameter lists in user code. Ideally I would like to be able to do this: mixin TemplateBuilder!(MyType, PresetTemplateArgs) MyChoiceOfBuilderName; where preset template args is optional and variadic, e.g. T in your example.
Nov 21 2014
prev sibling next sibling parent Artur Skawina via Digitalmars-d <digitalmars-d puremagic.com> writes:
On 11/21/14 14:39, monarch_dodra via Digitalmars-d wrote:
 D has phenomenal meta programming possibilities
[...]
     alias MyContainerType = ContainerBuilder!int
         //.setUseGC!??? //Don't care about GCm use default.
         .setScan!false
         .setUSomeOtherThing!true
         .Type;
 
 I think this is hugely neat. I'm posting here both to share, and
 for "peer review feedback".
You can just use a struct and D's phenomenal compile time programming possibilities. ;) struct fParms { int one = 1; string two = "one"; } alias fParm = TParm!fParms; auto f(alias P=fParm)() { // ... use P.$parm to access parameters ... pragma(msg, P.one, " ", P.two); } auto f2(alias P, A...)(A a) { f!P(); } auto f3(alias P, A...)(A a) { enum ALT = P.one = P.one+34; f!ALT(); } void main() { f(); f!(fParm.one=2)(); f!(fParm.two="three")(); enum a = "four"; f!((fParm.one=4).two=a)(); f!(fParm.one(4).two(a))(); enum b = "five"; f!(fParm.two=b)(); f!(fParm.one(6).two(b~"+1"))(); enum c = "seven"; f2!(fParm.two=c)(42); f3!(fParm.one=8)(42); } property TParm(alias Parms)() { static struct FParm { private Parms _parms; template opDispatch(string M) { ref opDispatch(B)(B b) property { mixin("_parms."~M) = b; return this; } auto opDispatch()() property { return mixin("_parms."~M); } } } return FParm(); } artur
Nov 22 2014
prev sibling next sibling parent "Oren Tirosh" <orent hishome.net> writes:
On Friday, 21 November 2014 at 13:39:43 UTC, monarch_dodra wrote:
 I trust everyone here knows about the "builder" pattern
 (http://en.wikipedia.org/wiki/Builder_pattern)? It can be very
 useful when the number of (optional) arguments in a function
 start to run rampant, and you know the user only wants to start
 setting a subset of these.

 D has phenomenal meta programming possibilities, and I see more
 and more templates taking more and more parameters. So I thought
 to myself, why not have a template builder pattern?

 I was able to throw this together:
 http://dpaste.dzfl.pl/366d1fc22c9c

 Which allows things like:
 	alias MyContainerType = ContainerBuilder!int
 		//.setUseGC!??? //Don't care about GCm use default.
 		.setScan!false
 		.setUSomeOtherThing!true
 		.Type;

 I think this is hugely neat. I'm posting here both to share, and
 for "peer review feedback".

 I'm also wondering if there is prior "literature" about this, 
 and
 if it's something we'd want more of in Phobos?
In this blog post http://tomerfiliba.com/blog/dlang a syntax based on overloading opDollar and opDispatch is proposed for key/value pairs: alias MyContainerType = ContainerBuilder!int[ $.Scan=false, $.SomeOtherThing=true ].Type; I still can't make up my mind if it's brilliant or blasphemous.
Nov 23 2014
prev sibling next sibling parent ketmar via Digitalmars-d <digitalmars-d puremagic.com> writes:
On Sat, 22 Nov 2014 17:36:02 +0100
Artur Skawina via Digitalmars-d <digitalmars-d puremagic.com> wrote:

 You can just use a struct and D's phenomenal compile time
 programming possibilities. ;)
heh. thank you, with `alias` and function instead of struct my compile-time formatted writter now works with both GDC and DMD. yay!
Nov 25 2014
prev sibling parent reply "Robik" <szadows gmail.com> writes:
On Friday, 21 November 2014 at 13:39:43 UTC, monarch_dodra wrote:
 I trust everyone here knows about the "builder" pattern
 (http://en.wikipedia.org/wiki/Builder_pattern)? It can be very
 useful when the number of (optional) arguments in a function
 start to run rampant, and you know the user only wants to start
 setting a subset of these.

 D has phenomenal meta programming possibilities, and I see more
 and more templates taking more and more parameters. So I thought
 to myself, why not have a template builder pattern?

 I was able to throw this together:
 http://dpaste.dzfl.pl/366d1fc22c9c

 Which allows things like:
 	alias MyContainerType = ContainerBuilder!int
 		//.setUseGC!??? //Don't care about GCm use default.
 		.setScan!false
 		.setUSomeOtherThing!true
 		.Type;

 I think this is hugely neat. I'm posting here both to share, and
 for "peer review feedback".

 I'm also wondering if there is prior "literature" about this, 
 and
 if it's something we'd want more of in Phobos?
If D would support getting parameter names(currently does not work for lambdas) of lambdas we could have: someConnect(host => "test", port => 7999); Just a random thought :)
Nov 26 2014
parent "Meta" <jared771 gmail.com> writes:
On Wednesday, 26 November 2014 at 17:42:07 UTC, Robik wrote:
 If D would support getting parameter names(currently does not 
 work for lambdas) of lambdas we could have:

    someConnect(host => "test", port => 7999);

 Just a random thought :)
import std.stdio; import std.traits; void main() { //Prints a blank line writeln(ParameterIdentifierTuple!((int n) => n)); } That's an annoying limitation. I've submitted a bug for it. https://issues.dlang.org/show_bug.cgi?id=13780
Nov 26 2014