From 4b75b134851154b1720986be5094d7f987fd77da Mon Sep 17 00:00:00 2001 From: Mike Cifelli Date: Sun, 15 Jan 2017 13:50:28 -0500 Subject: [PATCH] Refactored the code for math functions --- src/function/builtin/math/DIVIDE.java | 23 ++----------- src/function/builtin/math/MINUS.java | 27 ++++----------- src/function/builtin/math/MULTIPLY.java | 25 ++++---------- src/function/builtin/math/MathFunction.java | 37 +++++++++++++++++++++ src/function/builtin/math/PLUS.java | 25 ++++---------- 5 files changed, 59 insertions(+), 78 deletions(-) create mode 100644 src/function/builtin/math/MathFunction.java diff --git a/src/function/builtin/math/DIVIDE.java b/src/function/builtin/math/DIVIDE.java index 1d7e2af..394dfa7 100644 --- a/src/function/builtin/math/DIVIDE.java +++ b/src/function/builtin/math/DIVIDE.java @@ -8,36 +8,19 @@ import sexpression.*; public class DIVIDE extends LispFunction { private ArgumentValidator argumentValidator; + private MathFunction mathFunction; public DIVIDE() { this.argumentValidator = new ArgumentValidator("/"); this.argumentValidator.setMinimumNumberOfArguments(1); this.argumentValidator.setEveryArgumentExpectedType(LispNumber.class); + this.mathFunction = new MathFunction(this::getReciprocal, this::divide); } 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 getReciprocal(number1); - - SExpression secondArgument = remainingArguments.getCar(); - LispNumber number2 = (LispNumber) secondArgument; - LispNumber quotient = divide(number1, number2); - SExpression remainingNumbers = remainingArguments.getCdr(); - - if (remainingNumbers.nullp()) - return quotient; - - return callTailRecursive(new Cons(quotient, remainingNumbers)); + return mathFunction.callTailRecursive(argumentList); } private LispNumber getReciprocal(LispNumber number1) { diff --git a/src/function/builtin/math/MINUS.java b/src/function/builtin/math/MINUS.java index b809fa1..807e5a6 100644 --- a/src/function/builtin/math/MINUS.java +++ b/src/function/builtin/math/MINUS.java @@ -8,40 +8,27 @@ import sexpression.*; public class MINUS extends LispFunction { private ArgumentValidator argumentValidator; + private MathFunction mathFunction; public MINUS() { this.argumentValidator = new ArgumentValidator("-"); this.argumentValidator.setMinimumNumberOfArguments(1); this.argumentValidator.setEveryArgumentExpectedType(LispNumber.class); + this.mathFunction = new MathFunction(this::additiveInverse, this::subtract); } 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)); + return mathFunction.callTailRecursive(argumentList); } private LispNumber additiveInverse(LispNumber number) { return new LispNumber(BigInteger.ZERO.subtract(number.getValue())); } + private LispNumber subtract(LispNumber number1, LispNumber number2) { + return new LispNumber(number1.getValue().subtract(number2.getValue())); + } + } diff --git a/src/function/builtin/math/MULTIPLY.java b/src/function/builtin/math/MULTIPLY.java index 3b3f6aa..c48981d 100644 --- a/src/function/builtin/math/MULTIPLY.java +++ b/src/function/builtin/math/MULTIPLY.java @@ -6,35 +6,22 @@ import sexpression.*; public class MULTIPLY extends LispFunction { private ArgumentValidator argumentValidator; + private MathFunction mathFunction; public MULTIPLY() { this.argumentValidator = new ArgumentValidator("*"); this.argumentValidator.setEveryArgumentExpectedType(LispNumber.class); + this.mathFunction = new MathFunction(number -> number, this::multiply); } - public LispNumber call(Cons argumentList) { + public SExpression call(Cons argumentList) { argumentValidator.validate(argumentList); - return callTailRecursive(new Cons(LispNumber.ONE, argumentList)); + return mathFunction.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)); + private LispNumber multiply(LispNumber number1, LispNumber number2) { + return new LispNumber(number1.getValue().multiply(number2.getValue())); } } diff --git a/src/function/builtin/math/MathFunction.java b/src/function/builtin/math/MathFunction.java new file mode 100644 index 0000000..e211e5a --- /dev/null +++ b/src/function/builtin/math/MathFunction.java @@ -0,0 +1,37 @@ +package function.builtin.math; + +import java.util.function.*; + +import sexpression.*; + +class MathFunction { + + Function singleValueOperation; + BiFunction multipleValueOperation; + + public MathFunction(Function singleValueOperation, + BiFunction multipleValueOperation) { + this.singleValueOperation = singleValueOperation; + this.multipleValueOperation = multipleValueOperation; + } + + public SExpression callTailRecursive(Cons argumentList) { + Cons remainingArguments = (Cons) argumentList.getCdr(); + SExpression firstArgument = argumentList.getCar(); + LispNumber number1 = (LispNumber) firstArgument; + + if (remainingArguments.nullp()) + return singleValueOperation.apply(number1); + + SExpression secondArgument = remainingArguments.getCar(); + LispNumber number2 = (LispNumber) secondArgument; + LispNumber operationResult = multipleValueOperation.apply(number1, number2); + SExpression remainingNumbers = remainingArguments.getCdr(); + + if (remainingNumbers.nullp()) + return operationResult; + + return callTailRecursive(new Cons(operationResult, remainingNumbers)); + } + +} diff --git a/src/function/builtin/math/PLUS.java b/src/function/builtin/math/PLUS.java index d561732..a96a450 100644 --- a/src/function/builtin/math/PLUS.java +++ b/src/function/builtin/math/PLUS.java @@ -6,35 +6,22 @@ import sexpression.*; public class PLUS extends LispFunction { private ArgumentValidator argumentValidator; + private MathFunction mathFunction; public PLUS() { this.argumentValidator = new ArgumentValidator("+"); this.argumentValidator.setEveryArgumentExpectedType(LispNumber.class); + this.mathFunction = new MathFunction(number -> number, this::add); } - public LispNumber call(Cons argumentList) { + public SExpression call(Cons argumentList) { argumentValidator.validate(argumentList); - return callTailRecursive(new Cons(LispNumber.ZERO, argumentList)); + return mathFunction.callTailRecursive(new Cons(LispNumber.ZERO, 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 sum = new LispNumber(number1.getValue().add(number2.getValue())); - SExpression remainingNumbers = remainingArguments.getCdr(); - - if (!remainingNumbers.consp()) - return sum; - - return callTailRecursive(new Cons(sum, remainingNumbers)); + private LispNumber add(LispNumber number1, LispNumber number2) { + return new LispNumber(number1.getValue().add(number2.getValue())); } }