osiire’s blog

ふしぎなそふとやさん

Observer、haXe版

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;
	}
	
}