Re: Improve a simple event handler
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.
Re: Improve a simple event handler
On Saturday, 15 January 2022 at 23:15:16 UTC, JN wrote: I am writing a simple event handler object for observer pattern. https://gist.github.com/run-dlang/d58d084752a1f65148b33c796535a4e2 (note: the final implementation will use an array of listeners, Did you especially make an effort not to use money DI (Dependency injection)? Your codes will be more delicious if you implement DI. You can find its simple implementation [here.](https://forum.dlang.org/post/roqnezzxcuorscnma...@forum.dlang.org) If you get the ConnectionSetup working, you can setup without knowing the service parameters. Salih
Re: Improve a simple event handler
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. Looks good. But do note that with larger applications it inevitably becomes a ball of spaghetti, making it hard to understand why a certain widget behaves the way it does (or doesn't). The other problem - already apparent in this small example - is the absence of `removeListener`. It is a very crucial and often overlooked part that often only gets written afterwards. The problem is that it ties into lifetime which is hard to bolt on. For small things though, it works wonderfully.
Re: Improve a simple event handler
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.
Improve a simple event handler
I am writing a simple event handler object for observer pattern. https://gist.github.com/run-dlang/d58d084752a1f65148b33c796535a4e2 (note: the final implementation will use an array of listeners, but I want to keep it simple for now and have only one handler per event). Is there some way I could improve this with some D features? My main gripes with it are: 1) generic typing. I wish event handler methods such as onResize and onWindowTitle could take concrete types like WindowResize and WindowTitle rather than the generic Event struct. 2) same when emitting the event. It feels a bit verbose. I don't want to use classes or polymorphism. I was thinking perhaps std.variant could be useful here, although I am not exactly sure how it would work in practice.