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