I guess I’m still getting the hang of a few things here; my second contribution to Groovy Science takes most of what I did last time and tosses it out, all while making several major changes that could probably have been contributed individually. It seems to have taken me at least two days per revision thus far, and I think I should be shooting for about .7 days per revision. Maybe it’s just the fact that this is a brand new project….
Anyway, here are the changes. In case you’d like to see some examples, the unit tests in the TestScience class are probably pretty illustrative.
Expression validation is performed separately from expression construction. Before, each operator had its own validation method that made sure it was used properly. Now, any expression can be built (even if its operators make no sense whatsoever), and then it is shuffled into the context it’s wanted in as a second step. This shouldn’t have a significant impact on code, since the validation (and any necessary translation from “generic symbolic expression” to “domain-specific symbolic expression”) can be performed in a single function call.
Since the operators are no longer in charge of their own validation, they actually aren’t in charge of anything, and so they might as well be
Operator interface is no more, and in its place is the ability to use enum values (or anything else, really) as an operator. In a way, a
SymbolicExpression is no better than a glorified tree… and I never expected it to be.
I’ve overloaded all of the operators on
SymbolicExpression, and in fact I did use enum values for the operators there. The
OverloadableOperators enum lists all of the operators that I was able to overload.
For those who would still like some assurance that the expressions they build are well-formed, I’ve put in an
ExpressionValidator interface for use in making various specifications of what “well-formed” means, and I’ve implemented it as
CumulativeExpressionValidator, which makes it possible to specify one’s constraints—and exceptions to those constraints—one at a time. There is still some room for improvement, but this is enough for some practical use to begin.
Next up, I actually focus on making operators and a verifier for algebraic expressions with real-valued constants and variables. Maybe I’ll even extend this to algebraic equations and inequalities, or maybe I’ll add support for function-valued constants and variables and focus on evaluating the expressions. It’ll be a little while before any actual algebra is performed, though, I think.