package org.enumerable.lambda;
/**
* A function that takes three arguments.
*/
@SuppressWarnings("serial")
public abstract class Fn3<A1, A2, A3, R> extends Fn2<A1, A2, R> {
public abstract R call(A1 a1, A2 a2, A3 a3);
public R call(A1 a1, A2 a2) {
return call(a1, a2, default$3());
}
protected A3 default$3() {
return null;
}
@SuppressWarnings("unchecked")
public R apply(Object... args) {
if (args.length >= 3)
return call((A1) args[0], (A2) args[1], (A3) args[2]);
return super.apply(args);
}
/**
* Partial application, returns a {@link Fn2} which calls this function with
* a1 as the first argument.
*/
public Fn2<A2, A3, R> partial(final A1 a1) {
return new Fn2<A2, A3, R>() {
public R call(A2 a2, A3 a3) {
return Fn3.this.call(a1, a2, a3);
}
};
}
/**
* Currying Fn3 requires calling {@link #curry3()}.
*
* @throws UnsupportedOperationException
*/
public Fn1<A1, Fn1<A2, R>> curry2() {
throw new UnsupportedOperationException("Use curry3 to curry Fn3");
}
/**
* Currying, returns a {@link Fn1} which takes a1 as its argument and
* returns another Fn1 which takes a2, which returns another Fn1 which takes
* a3 which invokes this function with a1, a2 and a3 when called.
*/
public Fn1<A1, Fn1<A2, Fn1<A3, R>>> curry3() {
return new Fn1<A1, Fn1<A2, Fn1<A3, R>>>() {
public Fn1<A2, Fn1<A3, R>> call(final A1 a1) {
return new Fn1<A2, Fn1<A3, R>>() {
public Fn1<A3, R> call(final A2 a2) {
return new Fn1<A3, R>() {
public R call(A3 a3) {
return Fn3.this.call(a1, a2, a3);
}
};
}
};
}
};
}
public Fn3<A1, A2, A3, Boolean> complement() {
return new Fn3<A1, A2, A3, Boolean>() {
public Boolean call(A1 a1, A2 a2, A3 a3) {
return isFalseOrNull(Fn3.this.call(a1, a2, a3));
}
};
}
public int arity() {
return 3;
}
}