Thread overview
Can attributes trigger functionality?
Sep 06, 2017
Adam D. Ruppe
Sep 06, 2017
Moritz Maxeiner
September 06, 2017
I'm having to create a lot of boiler plate code that creates "events" and corresponding properties(getter and setter).

I'm curious if I can simplify this without a string mixin.

If I create my own attribute like

@Event double foo();

and I write any code that will trigger when the event is used and add more code(such as the setter property and events that I need?

Obviously I could write some master template that scans everything, but that seems to be far too much over kill. A string mixin is probably my only option but is a bit ulgy for me.

Since attributes can be defined by structures it seems natural that we could put functionality in them that are triggered when used but I'm unsure if D has such capabilities.

Thanks.





September 06, 2017
On Wednesday, 6 September 2017 at 02:43:20 UTC, Psychological Cleanup wrote:
>
> I'm having to create a lot of boiler plate code that creates "events" and corresponding properties(getter and setter).
>
> I'm curious if I can simplify this without a string mixin.


You certainly don't need a string mixin, but you do need some code to react to the attribute.

Here's one that generates a wrapper function on-demand:

---

import std.stdio;
import std.traits;

class Test {
        @cool void foo_() {
                writeln("cool function called");
        }

        mixin CoolFunctions;
}

// our UDA
enum cool;

// adds the decorator implementation
mixin template CoolFunctions() {
        template opDispatch(string name) if(hasUDA!(__traits(getMember, typeof(this), name ~ "_"), cool)) {
                auto opDispatch(Parameters!(__traits(getMember, typeof(this), name ~ "_")) params) {
                        writeln("cool before");
                        scope(success) {
                                writeln("cool after");
                        }
                        return __traits(getMember, this, name ~ "_")(params);
                }
        }
}

void main() {
        auto test = new Test();
        test.foo();
}

-----


No string mixin (uses a mixin template instead), and not even a loop over the functions - it does them on-demand when used via opDispatch.

September 06, 2017
On Wednesday, 6 September 2017 at 02:43:20 UTC, Psychological Cleanup wrote:
>
> I'm having to create a lot of boiler plate code that creates "events" and corresponding properties(getter and setter).
>
> I'm curious if I can simplify this without a string mixin.
>
> If I create my own attribute like
>
> @Event double foo();
>
> and I write any code that will trigger when the event is used and add more code(such as the setter property and events that I need?
>
> Obviously I could write some master template that scans everything, but that seems to be far too much over kill. A string mixin is probably my only option but is a bit ulgy for me.
>
> Since attributes can be defined by structures it seems natural that we could put functionality in them that are triggered when used but I'm unsure if D has such capabilities.
>
> Thanks.

User defined attributes (UDAs) are in and of themselves only (compile time) introspectable decoration [1] (they only carry information). If you want to trigger specific behaviour for things that are attributed with a UDA you indeed need to some custom written active component that introspects using `__traits(getAttributes, symbol) and generates injects generates the behaviour (e.g. using a string mixin as you noted).

[1] https://dlang.org/spec/attribute.html#UserDefinedAttribute