package function.builtin.math; import static sexpression.LispNumber.ONE; import function.ArgumentValidator; import function.FunctionNames; import function.LispFunction; import sexpression.Cons; import sexpression.LispNumber; @FunctionNames({ "*" }) public class MULTIPLY extends LispFunction { private ArgumentValidator argumentValidator; private MathFunction mathFunction; public MULTIPLY(String name) { this.argumentValidator = new ArgumentValidator(name); this.argumentValidator.setEveryArgumentExpectedType(LispNumber.class); this.mathFunction = new MathFunction(number -> number, this::multiply); } @Override public LispNumber call(Cons argumentList) { argumentValidator.validate(argumentList); return mathFunction.callTailRecursive(new Cons(ONE, argumentList)).invoke(); } private LispNumber multiply(LispNumber number1, LispNumber number2) { return new LispNumber(number1.getValue().multiply(number2.getValue())); } }