package itpl.util;
import itpl.util.Util;
class Observer<A>
{
var listener : Array<A -> Void> ;
public function new()
{
listener = new Array();
}
public function listen( l : A -> Void ) : Void
{
listener.push( l );
}
public function clear_listener() : Void
{
listener = new Array();
}
public function __fire( x : A ) : Void
{
for( l in listener ) {
l ( x );
}
}
public function map<B> ( f : A -> B ) : Observer<B>
{
var o : Observer<B> = new Observer();
this.listen( function(x) { o.__fire(f(x)); } );
return o;
}
public function filter<B> ( f : A -> Option<B> ) : Observer<B>
{
var o : Observer<B> = new Observer();
this.listen( function(x) {
return switch (f(x)) {
case Some (v) :
o.__fire( v );
case None :
null;
}
});
return o;
}
public function mergeSame ( o1 : Observer<A> ) : Observer<A>
{
var o : Observer<A> = new Observer();
this.listen ( o.__fire );
o1.listen ( o.__fire );
return o;
}
public function merge<B> ( o1 : Observer<B> ) : Observer<Either<A,B>>
{
var o : Observer<Either<A,B>> = new Observer();
this.listen ( function(x) { o.__fire ( Left(x) ); } );
o1.listen ( function(x) { o.__fire ( Right(x) ); } );
return o;
}
public function forall<B> ( o1 : Observer<B> ) : Observer<Pair<A,B>>
{
var o : Observer<Pair<A,B>> = new Observer();
var av : A = null;
var bv : B = null;
this.listen ( function(a) {
if(av == null) { av = a; }
if(bv != null) {
o.__fire( new Pair( a, bv ) );
}
});
o1.listen ( function(b) {
if(bv == null) { bv = b; }
if(av != null) {
o.__fire( new Pair( av, b ) );
}
});
return o;
}
}