calc: Nested Formulas with Rewrite Rules
11.11.7 Nested Formulas with Rewrite Rules
------------------------------------------
When ‘a r’ (‘calc-rewrite’) is used, it takes an expression from the top
of the stack and attempts to match any of the specified rules to any
part of the expression, starting with the whole expression and then, if
that fails, trying deeper and deeper sub-expressions. For each part of
the expression, the rules are tried in the order they appear in the
rules vector. The first rule to match the first sub-expression wins; it
replaces the matched sub-expression according to the NEW part of the
rule.
Often, the rule set will match and change the formula several times.
The top-level formula is first matched and substituted repeatedly until
it no longer matches the pattern; then, sub-formulas are tried, and so
on. Once every part of the formula has gotten its chance, the rewrite
mechanism starts over again with the top-level formula (in case a
substitution of one of its arguments has caused it again to match).
This continues until no further matches can be made anywhere in the
formula.
It is possible for a rule set to get into an infinite loop. The most
obvious case, replacing a formula with itself, is not a problem because
a rule is not considered to “succeed” unless the righthand side actually
comes out to something different than the original formula or
sub-formula that was matched. But if you accidentally had both ‘ln(a b)
:= ln(a) + ln(b)’ and the reverse ‘ln(a) + ln(b) := ln(a b)’ in your
rule set, Calc would run forever switching a formula back and forth
between the two forms.
To avoid disaster, Calc normally stops after 100 changes have been
made to the formula. This will be enough for most multiple rewrites,
but it will keep an endless loop of rewrites from locking up the
computer forever. (On most systems, you can also type ‘C-g’ to halt any
Emacs command prematurely.)
To change this limit, give a positive numeric prefix argument. In
particular, ‘M-1 a r’ applies only one rewrite at a time, useful when
you are first testing your rule (or just if repeated rewriting is not
what is called for by your application).
You can also put a “function call” ‘iterations(N)’ in place of a rule
anywhere in your rules vector (but usually at the top). Then, N will be
used instead of 100 as the default number of iterations for this rule
set. You can use ‘iterations(inf)’ if you want no iteration limit by
default. A prefix argument will override the ‘iterations’ limit in the
rule set.
[ iterations(1),
f(x) := f(x+1) ]
More precisely, the limit controls the number of “iterations,” where
each iteration is a successful matching of a rule pattern whose
righthand side, after substituting meta-variables and applying the
default simplifications, is different from the original sub-formula that
was matched.
A prefix argument of zero sets the limit to infinity. Use with
caution!
Given a negative numeric prefix argument, ‘a r’ will match and
substitute the top-level expression up to that many times, but will not
attempt to match the rules to any sub-expressions.
In a formula, ‘rewrite(EXPR, RULES, N)’ does a rewriting operation.
Here EXPR is the expression being rewritten, RULES is the rule, vector
of rules, or variable containing the rules, and N is the optional
iteration limit, which may be a positive integer, a negative integer, or
‘inf’ or ‘-inf’. If N is omitted the ‘iterations’ value from the rule
set is used; if both are omitted, 100 is used.