Calculable objects are the ones that can be manipulated during calculations. The main methods are calculate_next_step() and expand_and_reduce_next_step().
This is basically the case of all simple calculus objects (like Values, Items, Products etc.) but not the case of composed calculus objects (like Equations : you can not calculate an Equation, even if you can calculate each of its members separately).
Fields | Methods (provided) | Methods (must be reimplemented) |
---|---|---|
substitute() | calculate_next_step() | |
__iter__() | expand_and_reduce_next_step() | |
__next__() | get_iteration_list() | |
__len__() | ||
multiply_symbol_is_required() | ||
requires_brackets() | ||
requires_inner_brackets() | ||
is_displ_as_a_single_1() | ||
is_displ_as_a_single_0() | ||
is_displ_as_a_single_neutral() | ||
is_displ_as_a_single_minus_1() | ||
is_displ_as_a_single_int() | ||
is_displ_as_a_single_numeric_Item() |
calculate_next_step() will determine what is the next object during steps of numeric calculation.
For instance, if the expression is this Product : (2×3 - 5)×(7 + 3), calculate_next_step() should return this Product : (6 - 5)×10. If nothing can be calculated, then calculate_next_step() will return None.
expand_and_reduce_next_step() will determine the next object in the steps of expansion and reduction of literal expressions. For instance, if the expression is 3x(8x - 3) it will return 3x×8x + 3x×(-3). If nothing can be expanded neither reduced, it will return None.
substitute()'s role is to properly replace literal Values by numeric ones. The match is done using a dictionnary in argument. It is only reimplemented in Value, which will actually do the substitution. The Calculable.substitute() will only call recursively substitute() on each element of the object. At last, Value.substitute() will do the job. There's a substitute() method in SubstitutableEquality also, which acts in the same way as Calculable.substitute(). (Maybe it is possible to create a Substitutable class which would gather everything related to substitution and then use multiple heritage possibilities to give these methods to all classes that need them)
get_iteration_list() will help the __iter__() and __next__() methods to work properly. Calculables contain one or several elements and it is practical to be able to iter over them. __len__() will tell how many elements there are. (Actually I do think there may be a way to unify all this and to have a way to avoid to redefine these methods by giving all calculus objects a _element field which would be of length 1 for Item and Value...)
multiply_symbol_is_required(), requires_brackets() and requires_inner_brackets() are necessary to be able to display an expression correctly.
The is_displ_as_a_single_*() methods are there to check if an object is not just a single 1 (or anything else) embedded in another objet. For instance, if we have a Product of (Product containing a single Item 1) by Item x ; we should display x and not 1x ; so the method is_displ_as_a_single_1() will help to check that 'Product containing a single Item 1' is actually displayable as a single 1 (and in this case does not have to be displayed).