package net.varkhan.base.functor.functional;
import net.varkhan.base.functor.Functional;
/**
* <b></b>.
* <p/>
*
* @author varkhan
* @date 2/11/12
* @time 3:23 PM
*/
public abstract class AggregateFunctional<A,C> implements Functional<A,C> {
protected final Functional<A, C>[] funcs;
public AggregateFunctional(Functional<A, C>... funcs) {
this.funcs = funcs;
}
public Functional<A, C>[] components() {
return funcs.clone();
}
public abstract double invoke(A arg, C ctx);
public static <A,C> AggregateFunctional<A,C> sum(Functional<A, C>... funcs) {
return new AggregateFunctional<A,C>(funcs) {
@Override
public double invoke(A arg, C ctx) {
double val = 0;
for(Functional<A, C> f: funcs) {
val += f.invoke(arg, ctx);
}
return val;
}
@Override
public String toString() {
StringBuilder buf = new StringBuilder();
boolean f = true;
for(Functional<A,C> m: funcs) {
if(f) f = false;
else buf.append('+');
buf.append(m.toString());
}
return buf.toString();
}
};
}
public static <A,C> AggregateFunctional<A,C> prod(Functional<A, C>... funcs) {
return new AggregateFunctional<A,C>(funcs) {
@Override
public double invoke(A arg, C ctx) {
double val = 1;
for(Functional<A, C> f: funcs) {
val *= f.invoke(arg, ctx);
}
return val;
}
@Override
public String toString() {
StringBuilder buf = new StringBuilder();
boolean f = true;
for(Functional<A,C> m: funcs) {
if(f) f = false;
else buf.append('*');
buf.append(m.toString());
}
return buf.toString();
}
};
}
public static <A,C> AggregateFunctional<A,C> min(Functional<A, C>... funcs) {
return new AggregateFunctional<A,C>(funcs) {
@Override
public double invoke(A arg, C ctx) {
double val = Double.MAX_VALUE;
for(Functional<A, C> f: funcs) {
double v = f.invoke(arg, ctx);
if(val>v) val = v;
}
return val;
}
@Override
public String toString() {
StringBuilder buf = new StringBuilder("min");
buf.append('(');
boolean f = true;
for(Functional<A,C> m: funcs) {
if(f) f = false;
else buf.append(',');
buf.append(m.toString());
}
buf.append(')');
return buf.toString();
}
};
}
public static <A,C> AggregateFunctional<A,C> max(Functional<A, C>... funcs) {
return new AggregateFunctional<A,C>(funcs) {
@Override
public double invoke(A arg, C ctx) {
double val = -Double.MAX_VALUE;
for(Functional<A, C> f: funcs) {
double v = f.invoke(arg, ctx);
if(val<v) val = v;
}
return val;
}
@Override
public String toString() {
StringBuilder buf = new StringBuilder("max");
buf.append('(');
boolean f = true;
for(Functional<A,C> m: funcs) {
if(f) f = false;
else buf.append(',');
buf.append(m.toString());
}
buf.append(')');
return buf.toString();
}
};
}
protected String toString(String op) {
StringBuilder buf = new StringBuilder(op);
buf.append('(');
boolean f = true;
for(Functional<A,C> m: funcs) {
if(f) f = false;
else buf.append(',');
buf.append(m.toString());
}
buf.append(')');
return buf.toString();
}
@Override
public String toString() {
return toString(this.getClass().getSimpleName());
}
}