Improve a simple event handler
Hipreme
msnmancini at hotmail.com
Wed Jan 19 11:17:10 UTC 2022
On Sunday, 16 January 2022 at 20:01:09 UTC, JN wrote:
> On Saturday, 15 January 2022 at 23:15:16 UTC, JN wrote:
>>
>> Is there some way I could improve this with some D features?
>> My main gripes with it are:
>>
>
> Managed to dramatically simplify it to 10 lines of code with
> variadic templates.
>
> ```d
> import std.stdio;
>
> struct Event(T...)
> {
> void function(T)[] listeners;
>
> void addListener(void function(T) handler)
> {
> listeners ~= handler;
> }
>
> void emit(T args)
> {
> foreach (listener; listeners)
> {
> listener(args);
> }
> }
> }
>
> void onResize(uint newWidth, uint newHeight)
> {
> writefln("Resized: %d %d", newWidth, newHeight);
> }
>
> void main()
> {
> Event!(uint, uint) windowResizeEvent;
> windowResizeEvent.addListener(&onResize);
>
> windowResizeEvent.emit(1000, 2000);
> }
> ```
>
> I am very happy with this solution.
My advice is to make your listeners return a boolean. This
boolean is used to basically stop propagating the event. And
debugging it seems really hard to be honest, so, incrementing it
a little, I would do:
```d
struct ListenerInfo
{
string name;
string file;
uint line;
string registeredAt;
}
struct Event(T...)
{
bool function(T)[] listeners;
ListenerInfo[] info;
void addListener(bool function(T) handler, string name, string
file = __FILE__, uint line = __LINE__, string registeredAt =
__PRETTY_FUNCTION__)
{
listeners~= handler;
info~= ListenerInfo(name, file, line, registeredAt);
}
void emit(T args)
{
foreach(i, l; listeners)
{
if(l(args))
{
writeln(info[i]);
break;
}
}
}
}
```
You could even extend this concept further by making it return an
enum value for actually removing the listener when executed,
stopping propagation. Or you could have access to the listener
info inside the arguments too.
More information about the Digitalmars-d-learn
mailing list