package function.builtin; import java.math.BigInteger; import function.*; import sexpression.*; public class MINUS extends LispFunction { private ArgumentValidator argumentValidator; public MINUS() { this.argumentValidator = new ArgumentValidator("-"); this.argumentValidator.setMinimumNumberOfArguments(1); this.argumentValidator.setEveryArgumentExpectedType(LispNumber.class); } public SExpression call(Cons argumentList) { argumentValidator.validate(argumentList); return callTailRecursive(argumentList); } private SExpression callTailRecursive(Cons argumentList) { Cons remainingArguments = (Cons) argumentList.getCdr(); SExpression firstArgument = argumentList.getCar(); LispNumber number1 = (LispNumber) firstArgument; if (remainingArguments.nullp()) return additiveInverse(number1); SExpression secondArgument = remainingArguments.getCar(); LispNumber number2 = (LispNumber) secondArgument; LispNumber difference = new LispNumber(number1.getValue().subtract(number2.getValue())); SExpression remainingNumbers = remainingArguments.getCdr(); if (!remainingNumbers.consp()) return difference; return callTailRecursive(new Cons(difference, remainingNumbers)); } private LispNumber additiveInverse(LispNumber number) { return new LispNumber(BigInteger.ZERO.subtract(number.getValue())); } }