Re: Improve a simple event handler

2022-01-19 Thread Hipreme via Digitalmars-d-learn

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

2022-01-17 Thread Salih Dincer via Digitalmars-d-learn

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

2022-01-17 Thread Sebastiaan Koppe via Digitalmars-d-learn

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

2022-01-16 Thread JN via Digitalmars-d-learn

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

2022-01-15 Thread JN via Digitalmars-d-learn

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.