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.
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:
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.