package function.builtin; import function.*; import sexpression.*; public class MULTIPLY extends LispFunction { private ArgumentValidator argumentValidator; public MULTIPLY() { this.argumentValidator = new ArgumentValidator("*"); this.argumentValidator.setEveryArgumentExpectedType(LispNumber.class); } public LispNumber call(Cons argumentList) { argumentValidator.validate(argumentList); return callTailRecursive(new Cons(LispNumber.ONE, argumentList)); } private LispNumber callTailRecursive(Cons argumentList) { Cons remainingArguments = (Cons) argumentList.getCdr(); SExpression firstArgument = argumentList.getCar(); LispNumber number1 = (LispNumber) firstArgument; if (remainingArguments.nullp()) return number1; SExpression secondArgument = remainingArguments.getCar(); LispNumber number2 = (LispNumber) secondArgument; LispNumber product = new LispNumber(number1.getValue().multiply(number2.getValue())); SExpression remainingNumbers = remainingArguments.getCdr(); if (!remainingNumbers.consp()) return product; return callTailRecursive(new Cons(product, remainingNumbers)); } }