package function.builtin.predicate import function.ArgumentValidator import function.FunctionNames import function.LispFunction import sexpression.Cons import sexpression.LispNumber import sexpression.Nil import sexpression.SExpression import sexpression.Symbol.Companion.T @FunctionNames("=") class NumericEqual(name: String) : LispFunction() { private val argumentValidator = ArgumentValidator(name).apply { setMinimumNumberOfArguments(1) setEveryArgumentExpectedType(LispNumber::class.java) } override fun call(argumentList: Cons): SExpression { argumentValidator.validate(argumentList) return callTailRecursive(argumentList) } private tailrec fun callTailRecursive(argumentList: Cons): SExpression { val remainingArguments = argumentList.rest as Cons if (remainingArguments.isNull) return T val number1 = argumentList.first as LispNumber val number2 = remainingArguments.first as LispNumber return if (number1.value != number2.value) Nil else callTailRecursive(remainingArguments) } }