On 2010-07-07 10.48, Dmitry Olshansky wrote:
On 07.07.2010 2:47, BLS wrote:
Okay a bit better snippet than before. snippet should be almost
functional..

/*
Hi,
Andrei brings in the idea of std.pattern. Seems that this module is
"stalled"; Unfortunately !
However I would like to enhance collection classes (likewise
dcollections) with a Publisher - Subscriber pattern (signal - slot, or
observer pattern) , if you prefer)
Hope the idea of enhancing collections with events become clear with the
following snippet.
!!! I am able to spend just a few hours a month with D programming.. in
other words, please don't kill me :)
Untested Draft code which requires a lot of help and ,more important,
feedback from you.

*/

struct publisherMsg(T) {
T data;
Action a;
}

mixin template Publisher(T) {
private :

enum Action = {INSERT, UPDATE, DELETE, READONLY};
//alias typeof(this) PT;

struct receiver {
Object o;
callback cb;
}

receiver[] subscriber;

publisherMsg!(T) msg;

alias void delegate(const ref msg) callback;

void addSubscriber(object o, callback cb) {
//subscriber ~= o;
}

void publish() {
Now where are arguments? kind of (T t,Action act)
foreach (object o ; subscriber)
{
// create message and send message

}
}
The considerations are still the same :
foreach(c;subscriber)
c.callback(
see my erlier post
}


mixin template Subscriber() {
// see UndoList for implementation
}

final class Stack(T, bool observable = false ) {
T[] data;

static if (observable) mixin Observable!T;
Yes, I think Observable is more appropriate then Publisher. Then maybe
methods should be:
addObserver instead of addSubscriber,
notify instead of publish?
But back to the whole idea - I'm sure you do not want to reimplement all
the shiny std.container.
What I think we basically need is universal wrapper for _any_ container
stuff.
let's call that Observable!Cont. Something like :
final class Observable(Cont){
Cont cont;
//here goes your current Publisher stuff
//...
alias Cont!ElementType T;
static if(__traits(compiles,cont.insert(T.init)))//some such ... need to
test if it has this method
{
size_t insert(Stuff)(Stuff s){//trouble is - we could insert anything
that converts to T
size_t n = cont.insert(s);
notify(cast!(T)s,Action.Insert);
}
}
//and all such stuff from std.continer.TotalContainer
//in theory could even be generated from phobos source
....
}
usage :
alias Observable!(Array!int) observableArray;
observableArray arr = [ 4,5,6]; //that would be nice
arr.addObserver( (ref msg m){ writeln("arr insertion:
",to!string(m.data,m.action));
arr.insert(42); //should print that fancy message
...
Yes, I still think that plain delegates approach is more flexible and
straightforward (see my earlier post).

void push( T t) {
data ~= t;
publish(t, Action.INSERT);
}
T pop() {
publish(t, Action.DELETE);
//...
}
bool empty() {

}
T top() {
publish(t, Action.READONLY);
//...
}
size_t size() {

}
}
// Undo list will receive every pushed or popped item -data and action)
class UndoList(T) {
private:
T[] data;

/// should be part of the sunscriber mixin templates.
publisherMsg!T stackMessage;

void delegate(const ref stackMessage) dg;

alias Stack!(int) IntegerStack;

IntegerStack intstack = new IntegerStack;

private this() {
dg = &this.feedback;

// SUBBSCRIBE Stack(T) push and pop events.
intstack.addSubscriber(this, dg);
Again from my POV it could be:
intstack.addSubcriber(
(const ref stackMessage msg){ feedback(msg); }
);
//somewhat scary in this case, but in fact it does not restrict you to
class instances.

}
public void feedback(const ref stackMessage msg ) {
writefln("Action");
}
}
BTW I'm definitely interesed in this effort, and in fact want that kind
of functionality for my upcoming gui lib.
It all just needs to be more reusable and flexible.

I think it would be nice to simulate the events in C#. It's quite easy, just a struct containing a linked list of delegates, a function to call all the delegates and functions to add and remove delegates from the list.


--
Jacob Carlborg

Reply via email to