I want to add a Phobos module with template mixins for common idioms.

Idan Arye GenericNPC at gmail.com
Mon May 6 12:14:33 PDT 2013


Template mixins can be used to implement some common programming 
idioms(and design patterns). I have already implemented two of 
them for my own project - and I want to make them into a Phobos 
module - maybe `std.mixins`. The wiki at 
http://wiki.dlang.org/Review/Process says that before I start a 
new module contribution, I should post here to see if the 
community actually wants it, so this is what I'm doing.

The first one is the property idiom - a pair of getter and setter 
methods used to mutate a private member field. I have created 
four variants:
`propertyGetterOnly` - creates only the field and the getter.
`property` - creates the field, a getter and a setter.
`propertyAsserted` - creates the field, a getter and a setter 
that verifies it's input using an assert.
`propertyVerified` - creates the field, a getter and a setter 
that verifies it's input using an `if` statement and throws 
`PropertyException` if you try setting it to a bad value.

For example:

     class Foo
     {
         //Add an `int` property with value of 44, that can not 
exceed 60.
         mixin propertyVerified!(int, "x", `a <= 60`, 44);
     }

     Foo foo = new Foo();
     writeln(foo.x); //Prints 44
     foo.x = 55;
     writeln(foo.x); //Prints 55
     foo.x = 66; //throws PropertyException


The second idiom is the singleton pattern. I implemented it using 
the check-lock-check version, but I want to change the 
implementation to Dave's and Alexander Terekhov's low lock 
version(http://forum.dlang.org/thread/pelhvaxwjzhehdjtpsav@forum.dlang.org). 
At any rate, it'll be used like this

     class Foo
     {
         mixin lowLockSingleton!false;

         private this(/*args*/)
         {
             ...
         }

         void init(/*args*/)
         {
             singleton_initInstance(new Foo(/*args*/));
         }
     }

The `false` sent to `lowLockSingleton` means you don't want to 
automatically initialize your singleton when someone request an 
instance before it was initialized - this is useful if you want 
to send initialization arguments. You could set it to 
`true`(which will be the default) and get a regular singleton, 
but I want to elaborate on this version. `lowLockSingleton` 
creates a private static method named `singleton_initInstance` 
which accepts a lazy argument for constructing the global 
instance. You need to implement your own initialization method, 
which should call `singleton_initInstance` to set the global 
instance based on initialization arguments. The 
`lowLockSingleton` implementation will make sure that only one 
call to `singleton_initInstance` will invoke the lazy argument 
and set the global instance to it's result.

I also want to implement a thread local singleton. That's it for 
now, but I think that's enough to justify a new module and once 
this module is up and running I'm sure other people will have 
other common and why-the-heck-is-this-not-common idioms to add.



The rationale behind having those template mixin is laziness. I'm 
a lazy programmer, and I know I'm not the only one.

I *know* I should use properties, and I know why, but it's so 
much easier to just use public fields. If I'll need getter&setter 
properties I can always change it later for just the fields where 
I need it, and if someone else needs them than it's their 
problem, not mine.

I *know* I should make my singletons thread-safe, and I know how, 
but the unsafe version is easier and between us, what are the 
chances for a race condition? *wink wink*

Having this `std.mixins` will make the right way also be the easy 
way. Writing `mixin property!(int, "x");` is not that bad, and 
since I can easily throw in a value check - I might just as well 
do it! And while the unsafe singleton is easier to implement than 
the safe version - not to mention the low lock version(they are 
not really *that* hard, but still harder than the unsafe version) 
- using `mixin lowLockSingleton;` is so much easier.



So, I would like to hear opinions. I already have a crude 
implementation of those two idioms, but I need to polish it some 
more before it's Phobos-worthy.

I also have a question about the contribution process. I know 
that when you contribute a small enhancement you need to open an 
enhancement issue on Bugzilla, but the modules in the review 
queue don't seem to have one. Are enhancement issues not required 
for a module contribution? Is this forum thread used instead of 
the Bugzilla issue to discuss the contribution?
Also, the wiki says that big features should start on their own 
feature 
branch(http://wiki.dlang.org/Development_and_Release_Process#Official_branches), 
but the modules on the review queue that have a GitHub pull 
request are pull-requested directly to master. Does that mean 
that what the wiki says is obsolete, or that the fork that these 
modules were developed on is in fact the feature branch?


Thanks for suffering through my long post!


More information about the Digitalmars-d mailing list