package function.builtin.predicate; import static recursion.TailCalls.done; import static recursion.TailCalls.tailCall; import static sexpression.Nil.NIL; import static sexpression.Symbol.T; import function.ArgumentValidator; import function.FunctionNames; import function.LispFunction; import recursion.TailCall; import sexpression.Cons; import sexpression.LispNumber; import sexpression.SExpression; @FunctionNames({ ">" }) public class NUMERIC_GREATER extends LispFunction { private ArgumentValidator argumentValidator; public NUMERIC_GREATER(String name) { this.argumentValidator = new ArgumentValidator(name); this.argumentValidator.setMinimumNumberOfArguments(1); this.argumentValidator.setEveryArgumentExpectedType(LispNumber.class); } @Override public SExpression call(Cons argumentList) { argumentValidator.validate(argumentList); return callTailRecursive(argumentList).invoke(); } private TailCall callTailRecursive(Cons argumentList) { Cons remainingArguments = (Cons) argumentList.getRest(); if (remainingArguments.isNull()) return done(T); SExpression firstArgument = argumentList.getFirst(); SExpression secondArgument = remainingArguments.getFirst(); LispNumber number1 = (LispNumber) firstArgument; LispNumber number2 = (LispNumber) secondArgument; if (!isFirstGreater(number1, number2)) return done(NIL); return tailCall(() -> callTailRecursive(remainingArguments)); } private boolean isFirstGreater(LispNumber number1, LispNumber number2) { return number1.getValue().compareTo(number2.getValue()) > 0; } }