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