Refactored the code for math functions
This commit is contained in:
parent
0560c02093
commit
4b75b13485
|
@ -8,36 +8,19 @@ import sexpression.*;
|
||||||
public class DIVIDE extends LispFunction {
|
public class DIVIDE extends LispFunction {
|
||||||
|
|
||||||
private ArgumentValidator argumentValidator;
|
private ArgumentValidator argumentValidator;
|
||||||
|
private MathFunction mathFunction;
|
||||||
|
|
||||||
public DIVIDE() {
|
public DIVIDE() {
|
||||||
this.argumentValidator = new ArgumentValidator("/");
|
this.argumentValidator = new ArgumentValidator("/");
|
||||||
this.argumentValidator.setMinimumNumberOfArguments(1);
|
this.argumentValidator.setMinimumNumberOfArguments(1);
|
||||||
this.argumentValidator.setEveryArgumentExpectedType(LispNumber.class);
|
this.argumentValidator.setEveryArgumentExpectedType(LispNumber.class);
|
||||||
|
this.mathFunction = new MathFunction(this::getReciprocal, this::divide);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SExpression call(Cons argumentList) {
|
public SExpression call(Cons argumentList) {
|
||||||
argumentValidator.validate(argumentList);
|
argumentValidator.validate(argumentList);
|
||||||
|
|
||||||
return callTailRecursive(argumentList);
|
return mathFunction.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));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private LispNumber getReciprocal(LispNumber number1) {
|
private LispNumber getReciprocal(LispNumber number1) {
|
||||||
|
|
|
@ -8,40 +8,27 @@ import sexpression.*;
|
||||||
public class MINUS extends LispFunction {
|
public class MINUS extends LispFunction {
|
||||||
|
|
||||||
private ArgumentValidator argumentValidator;
|
private ArgumentValidator argumentValidator;
|
||||||
|
private MathFunction mathFunction;
|
||||||
|
|
||||||
public MINUS() {
|
public MINUS() {
|
||||||
this.argumentValidator = new ArgumentValidator("-");
|
this.argumentValidator = new ArgumentValidator("-");
|
||||||
this.argumentValidator.setMinimumNumberOfArguments(1);
|
this.argumentValidator.setMinimumNumberOfArguments(1);
|
||||||
this.argumentValidator.setEveryArgumentExpectedType(LispNumber.class);
|
this.argumentValidator.setEveryArgumentExpectedType(LispNumber.class);
|
||||||
|
this.mathFunction = new MathFunction(this::additiveInverse, this::subtract);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SExpression call(Cons argumentList) {
|
public SExpression call(Cons argumentList) {
|
||||||
argumentValidator.validate(argumentList);
|
argumentValidator.validate(argumentList);
|
||||||
|
|
||||||
return callTailRecursive(argumentList);
|
return mathFunction.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) {
|
private LispNumber additiveInverse(LispNumber number) {
|
||||||
return new LispNumber(BigInteger.ZERO.subtract(number.getValue()));
|
return new LispNumber(BigInteger.ZERO.subtract(number.getValue()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private LispNumber subtract(LispNumber number1, LispNumber number2) {
|
||||||
|
return new LispNumber(number1.getValue().subtract(number2.getValue()));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,35 +6,22 @@ import sexpression.*;
|
||||||
public class MULTIPLY extends LispFunction {
|
public class MULTIPLY extends LispFunction {
|
||||||
|
|
||||||
private ArgumentValidator argumentValidator;
|
private ArgumentValidator argumentValidator;
|
||||||
|
private MathFunction mathFunction;
|
||||||
|
|
||||||
public MULTIPLY() {
|
public MULTIPLY() {
|
||||||
this.argumentValidator = new ArgumentValidator("*");
|
this.argumentValidator = new ArgumentValidator("*");
|
||||||
this.argumentValidator.setEveryArgumentExpectedType(LispNumber.class);
|
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);
|
argumentValidator.validate(argumentList);
|
||||||
|
|
||||||
return callTailRecursive(new Cons(LispNumber.ONE, argumentList));
|
return mathFunction.callTailRecursive(new Cons(LispNumber.ONE, argumentList));
|
||||||
}
|
}
|
||||||
|
|
||||||
private LispNumber callTailRecursive(Cons argumentList) {
|
private LispNumber multiply(LispNumber number1, LispNumber number2) {
|
||||||
Cons remainingArguments = (Cons) argumentList.getCdr();
|
return new LispNumber(number1.getValue().multiply(number2.getValue()));
|
||||||
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));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
package function.builtin.math;
|
||||||
|
|
||||||
|
import java.util.function.*;
|
||||||
|
|
||||||
|
import sexpression.*;
|
||||||
|
|
||||||
|
class MathFunction {
|
||||||
|
|
||||||
|
Function<LispNumber, LispNumber> singleValueOperation;
|
||||||
|
BiFunction<LispNumber, LispNumber, LispNumber> multipleValueOperation;
|
||||||
|
|
||||||
|
public MathFunction(Function<LispNumber, LispNumber> singleValueOperation,
|
||||||
|
BiFunction<LispNumber, LispNumber, LispNumber> 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));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -6,35 +6,22 @@ import sexpression.*;
|
||||||
public class PLUS extends LispFunction {
|
public class PLUS extends LispFunction {
|
||||||
|
|
||||||
private ArgumentValidator argumentValidator;
|
private ArgumentValidator argumentValidator;
|
||||||
|
private MathFunction mathFunction;
|
||||||
|
|
||||||
public PLUS() {
|
public PLUS() {
|
||||||
this.argumentValidator = new ArgumentValidator("+");
|
this.argumentValidator = new ArgumentValidator("+");
|
||||||
this.argumentValidator.setEveryArgumentExpectedType(LispNumber.class);
|
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);
|
argumentValidator.validate(argumentList);
|
||||||
|
|
||||||
return callTailRecursive(new Cons(LispNumber.ZERO, argumentList));
|
return mathFunction.callTailRecursive(new Cons(LispNumber.ZERO, argumentList));
|
||||||
}
|
}
|
||||||
|
|
||||||
private LispNumber callTailRecursive(Cons argumentList) {
|
private LispNumber add(LispNumber number1, LispNumber number2) {
|
||||||
Cons remainingArguments = (Cons) argumentList.getCdr();
|
return new LispNumber(number1.getValue().add(number2.getValue()));
|
||||||
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));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue