Thread overview
"Named parameter builder" pattern for template parameters
Nov 21, 2014
monarch_dodra
Nov 21, 2014
ketmar
Nov 21, 2014
monarch_dodra
Nov 21, 2014
John Colvin
Nov 22, 2014
Artur Skawina
Nov 23, 2014
Oren Tirosh
Nov 25, 2014
ketmar
Nov 26, 2014
Robik
Nov 26, 2014
Meta
November 21, 2014
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?
November 21, 2014
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.


November 21, 2014
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.
November 21, 2014
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.
November 22, 2014
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
November 23, 2014
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.
November 25, 2014
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!


November 26, 2014
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 :)
November 26, 2014
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