Rules

Rules are a core part of the way Mathematica and Mathics3 execute a program.

Expressions which are transformed by rewrite rules (AKA transformation rules) are handed by the Rule class.

There are also rules for how to match, assign function parameter arguments, and then apply a Python “evaluation” function to a Mathics3 Expression. These kinds of rules are handled by objects in the FunctionApplyRule class.

The module mathics.core.rules contains the classes for these two types of rules.

In a FunctionApplyRule rule, the match status of a rule depends on the evaluation return.

For example, suppose that we try to apply rule F[x_]->x^2 to the expression F[2]. The pattern part of the rule, F[x_] matches the expression, Blank[x] (or x_) is replaced by 2, giving the substitution expression 2^2. Evaluation then stops looking for other rules to be applied over F[2].

On the other hand, suppose that we define a FunctionApplyRule that associates F[x_] with the function:

...
class MyFunction(Builtin) -> Optional[Expression]:
    ...
    def eval_f(self, x, evaluation: Evaluation):
       "F[x_]"   # pattern part of FunctionApplyRule
        if x>3:
            return Expression(SymbolPower, x, Integer2)
       return None

Then, if we apply the rule to F[2], the function is evaluated returning None. Then, in the evaluation loop, we get the same effect as if the pattern didn’t match with the expression. The loop continues then with the next rule associated with F.

Why do things this way?

Sometimes, the cost of deciding if the rule match is similar to the cost of evaluating the function. Suppose for example a rule:

F[x_/;(G[x]>0)]:=G[x]

with G[x] a computationally expensive function. To decide if G[x] is larger than 0, we need to evaluate it, and once we have evaluated it, just need to return its value.

Also, this allows us to handle several rules in the same function, without relying on our very slow pattern-matching routines. In particular, this is used for for some critical low-level tasks like building lists in iterators, processing arithmetic expressions, plotting functions, or evaluating derivatives and integrals.