Up | Next | Prev | PrevTail | Tail |
Unlike substitutions introduced via sub
, let
rules are global in scope and stay in
effect until replaced or clear
ed.
The simplest use of the let
statement is in the form
let
\(\langle \)substitution list\(\rangle \)where \(\langle \)substitution list\(\rangle \) is a list of rules separated by commas, each of the form:
=>
\(\langle \)expression\(\rangle \)or
(
\(\langle \)argument\(\rangle \), …, \(\langle \)argument\(\rangle \)) =>
\(\langle \)expression\(\rangle \)or
=>
\(\langle \)expression\(\rangle \)For example,
let {x => y^2, h(u,v) => u - v, cos(pi/3) => 1/2, a*b => c, l+m => n, w^3 => 2*z - 3, z^10 => 0}
An equal sign (=
) can be used instead of the “replaceby” sign (=>
) and the list brackets
can be left out if preferred. The above rules could also have been entered as seven
separate let
statements.
After such let
rules have been input, x
will always be evaluated as the square of y
, and
so on. This is so even if at the time the let
rule was input, the variable y
had a value
other than y
. (In contrast, the assignment x:=y^2
will set x
equal to the square of the
current value of y
, which could be quite different.)
The rule let a*b=>c
means that whenever a
and b
are both factors in an expression
their product will be replaced by c
. For example, a^5*b^7*w
would be replaced by
c^5*b^2*w
.
The rule for l+m
will not only replace all occurrences of l+m
by n
, but will also
normally replace l
by n-m
, but not m
by n-l
. A more complete description of this case
is given in Section 11.2.5.
The rule pertaining to w^3
will apply to any power of w
greater than or equal to the
third.
Note especially the last example, let z^10=>0
. This declaration means, in effect:
ignore the tenth or any higher power of z
. Such declarations, when appropriate, often
speed up a computation to a considerable degree. (See Section 11.4 for more
details.)
Any new operators occurring in such let
rules will be automatically declared
operator
by the system, if the rules are being read from a file. If they are being
entered interactively, the system will ask Declare
… operator? (Y or N)
.
Answer Y
or N
and hit Return.
In each of these examples, substitutions are only made for the explicit expressions given; i.e., none of the variables may be considered arbitrary in any sense. For example, the command
let h(u,v) => u - v;
will cause h(u,v)
to evaluate to u - v
, but will not affect h(u,z)
or h
with any
arguments other than precisely the symbols u,v
.
These simple let
rules are on the same logical level as assignments made with the :=
operator. An assignment x := p+q
cancels a rule let x => y^2
made earlier, and
vice versa.
CAUTION: A recursive rule such as
let x => x + 1;
is erroneous, since any subsequent evaluation of x
would lead to a non-terminating chain
of substitutions:
x -> x + 1 -> (x + 1) + 1 -> ((x + 1) + 1) + 1 -> ...
Similarly, coupled substitutions such as
let l => m + n, n => l + r;
would lead to the same error. As a result, if you try to evaluate an x
, l
or n
defined as
above, you will get an error such as
x improperly defined in terms of itself
Array and matrix elements can appear on the left-hand side of a let
statement.
However, because of their instant evaluation property, it is the value of the element that
is substituted for, rather than the element itself. E.g.,
array a(5); a(2) := b; let a(2) => c;
results in b
being substituted by c
; the assignment for a(2)
does not change.
Finally, if an error occurs in any equation in a let
statement (including generalized
statements involving for all
and such that
), the remaining rules are not
evaluated.
If a substitution for all possible values of a given argument of an operator is
required, the declaration for all
may be used. The syntax of such a command
is
for all
\(\langle \)variable\(\rangle \), …, \(\langle \)variable\(\rangle \) \(\langle \)let statement\(\rangle \)\(\langle \)terminator\(\rangle \)e.g.,
for all x,y let h(x,y) => x-y; for all x let k(x,y) => x^y;
The first of these declarations would cause h(a,b)
to be evaluated as a-b
,
h(u+v,u+w)
as v-w
, etc. If the operator symbol h
is used with more or fewer
arguments, not two, the let
would have no effect, and no error would result.
The second declaration would cause k(a,y)
to be evaluated as a^y
, but would have no
effect on k(a,z)
since the rule didn’t say for all y
….
Where we used x
and y
in the examples, any variables could have been used. This use
of a variable doesn’t affect the value it may have outside the let
statement.
However, you should remember what variables you actually used. If you want to
delete the rule subsequently, you must use the same variables in the clear
command.
It is possible to use more complicated expressions as a template for a let
statement, as
explained in the section on substitutions for general expressions. In nearly all cases, the
rule will be accepted, and a consistent application made by the system. However, if there
is a sole constant or a sole free variable on the left-hand side of a rule (e.g., let 2 =>
3
or for all x let x => 2
), then the system is unable to handle the rule, and the
error message
Substitution for ... not allowed
will be issued. Any variable listed in the for all
part will have its symbol preceded
by an equal sign: x
in the above example will appear as =x
. An error will also occur if a
variable in the for all
part is not properly matched on both sides of the let
equation.
If a substitution is desired for more than a single value of a variable in an operator or
other expression, but not all values, a conditional form of the for all … let
declaration can be used.
Example:
for all x such that numberp x and x<0 let h(x)=>0;
will cause h(-5)
to be evaluated as 0, but h
of a positive integer, or of an argument that
is not an integer at all, would not be affected. Any boolean expression can follow the
such that
keywords.
The user may remove all assignments and substitution rules from any expression by the
command clear
, in the form
clear
\(\langle \)expression\(\rangle \), …, \(\langle \)expression\(\rangle \)\(\langle \)terminator\(\rangle \)e.g.
clear x, h(x,y);
Because of their instant evaluation property, array and matrix elements cannot be
cleared with clear
. For example, if a
is an array, you must say
a(3) := 0;
rather than
clear a(3);
to “clear” element a(3)
.
On the other hand, a whole array (or matrix) a
can be cleared by the command clear
a
; This means much more than resetting to 0 all the elements of a
. The fact that a
is an
array, and what its dimensions are, are forgotten, so a
can be redefined as another type of
object, for example an operator.
If you need to clear a variable whose name must be computed, see the unset
statement.
The more general types of let
declarations can also be deleted by using clear
.
Simply repeat the let
rule to be deleted, using clear
in place of let
, and
omitting the equal sign and right-hand part. The same dummy variables must be
used in the for all
part, and the boolean expression in the such that
part must be written the same way. (The placing of blanks doesn’t have to be
identical.)
Example: The let
rule
for all x such that numberp x and x<0 let h(x)=>0;
can be erased by the command
for all x such that numberp x and x<0 clear h(x);
clear
is not the only way to delete a let
rule. A new let
rule identical to the first, but
with a different expression after the equal sign, replaces the first. Replacements are also
made in other cases where the existing rule would be in conflict with the new rule. For
example, a rule for x^4
would replace a rule for x^5
. The user should however be
cautioned against having several let
rules in effect that relate to the same expression.
No guarantee can be given as to which rules will be applied by REDUCE or in
what order. It is best to clear
an old rule before entering a new related let
rule.
The examples of substitutions discussed in other sections have involved very simple rules. However, the substitution mechanism used in REDUCE is very general, and can handle arbitrarily complicated rules without difficulty.
The general substitution mechanism used in REDUCE is discussed in [Hea68],
and [Hea69]. For the reasons given in these references, REDUCE does not
attempt to implement a general pattern matching algorithm. However, the present
system uses far more sophisticated techniques than those discussed in the above
papers. It is now possible for the rules appearing in arguments of let
to have the
form
=>
\(\langle \)expression\(\rangle \)where any rule to which a sensible meaning can be assigned is permitted. However, this meaning can vary according to the form of \(\langle \)substitution expression\(\rangle \). The semantic rules associated with the application of the substitution are completely consistent, but somewhat complicated by the pragmatic need to perform such substitutions as efficiently as possible. The following rules explain how the majority of the cases are handled.
To begin with, the \(\langle \)substitution expression\(\rangle \) is first partly simplified by collecting like
terms and putting identifiers (and kernels) in the system order. However, no substitutions
are performed on any part of the expression with the exception of expressions with the
instant evaluation property, such as array and matrix elements, whose actual values are
used. It should also be noted that the system order used is not changeable by
the user, even with the korder
command. Specific cases are then handled as
follows:
*
appears at the top level of the simplified left-hand side, then any
constant arguments in that expression are moved to the right-hand side of the rule.
The remaining left-hand side is then added to the appropriate table. For
example,
let 2*x*y => 3
becomes
let x*y => 3/2
so that x*y
is added to the product substitution table, and when this rule is
applied, the expression x*y
becomes 3/2, but neither x
nor y
by themselves are
replaced.
+
, -
or /
appear at the top level of the simplified left-hand side, all
but the first term is moved to the right-hand side of the rule. Thus the
rules
let l+m=>n, x/2=>y, a-b=>c
become
let l=>n-m, x=>2*y, a=>c+b.
One problem that can occur in this case is that if a quantified expression is moved to the right-hand side, a given free variable might no longer appear on the left-hand side, resulting in an error because of the unmatched free variable. E.g.,
for all x,y let f(x)+f(y)=>x*y
would become
for all x,y let f(x)=>x*y-f(y)
which no longer has y
on both sides.
The fact that array and matrix elements are evaluated in the left-hand side of rules can lead to confusion at times. Consider for example the statements
array a(5); let x+a(2)=>3; let a(3)=>4;
The left-hand side of the first rule will become x
, and the second 0. Thus the first
rule will be instantiated as a substitution for x
, and the second will result in an
error.
The order in which a list of rules is applied is not easily understandable without a detailed knowledge of the system simplification protocol. It is also possible for this order to change from release to release, as improved substitution techniques are implemented. Users should therefore assume that the order of application of rules is arbitrary, and program accordingly.
After a substitution has been made, the expression being evaluated is reexamined in case a new allowed substitution has been generated. This process is continued until no more substitutions can be made.
As mentioned elsewhere, when a substitution expression appears in a product, the substitution is made if that expression divides the product. For example, the rule
let a^2*c => 3*z;
would cause a^2*c*x
to be replaced by 3*z*x
and a^2*c^2
by 3*z*c
. If the
substitution is desired only when the substitution expression appears in a product with
the explicit powers supplied in the rule, the command match
should be used
instead..
For example,
match a^2*c => 3*z;
would cause a^2*c*x
to be replaced by 3*z*x
, but a^2*c^2
would not be
replaced. match
can also be used with the for all
constructions described
above.
To remove substitution rules of the type discussed in this section, the clear
command
can be used, combined, if necessary, with the same for all
clause with which the rule
was defined, for example:
for all x clear log(e^x),e^log(x),cos(w*t+theta(x));
Note, however, that the arbitrary variable names in this case must be the same as those used in defining the substitution.
Up | Next | Prev | PrevTail | Front |