LET _ _ _ _ _ _ _ _ _ _ _ _ command
The let command defines general or specific substitution rules.
let<identifier> = <expression>{,<identifier> = <expression>}*
<identifier> can be any valid REDUCE identifier except an array, and in some cases can be an expression; <expression> can be any valid REDUCE expression.
let a = sin(x); b := a; B := SIN X; let c = a; exp(a); SIN(X) E a := x**2; 2 A := X exp(a); 2 X E exp(b); SIN(X) E exp(c); 2 X E let m + n = p; (m + n)**5; 5 P operator h; let h(u,v) = u - v; h(u,v); U - V h(x,y); H(X,Y) array q(10); let q(1) = 15; ***** Substitution for 0 not allowed
The let command is also used to activate a rule sets .
let<list>{,<list>}+
<list> can be an explicit rule list, or evaluate to a rule list.
trig1 := {cos(~x)*cos(~y) => (cos(x+y)+cos(x-y))/2, cos(~x)*sin(~y) => (sin(x+y)-sin(x-y))/2, sin(~x)*sin(~y) => (cos(x-y)-cos(x+y))/2, cos(~x)^2 => (1+cos(2*x))/2, sin(~x)^2 => (1-cos(2*x))/2}$ let trig1; cos(a)*cos(b); COS(A - B) + COS(A + B) ------------------------ 2
A let command returns no value, though the substitution r ule is entered. Assignment rules made by assign and let rules are at the same level, and cancel each other. There is a difference in their operation, however, as shown in the first example: a let assignment tracks the changes in what it is assigned to, while a := assignment is fixed at the value it originally had.
The use of expressions as left-hand sides of let statements is a little complicated. The rules of operation are:
_ _ _ (i) Expressions of the form A*B = C do not change A, B or C, but set A*B to C.
_ _ _ (ii) Expressions of the form A+B = C substitute C - B for A, but do not change B or C.
_ _ _ (iii) Expressions of the form A-B = C substitute B + C for A, but do not change B or C.
_ _ _ (iv) Expressions of the form A/B = C substitute B*C for A, but do not change B or C.
_ _ _ (v) Expressions of the form A**N = C substitute C for A**N in every expression of a power of A to N or greater. An asymptotic command such as A**N = 0 sets all terms involving A to powers greater than or equal to N to 0. Finite fields may be generated by requiring modular arithmetic (the modular switch) and defining the primitive polynomial via a let statement.
letsubstitutions involving expressions are cleared by using the clear command with exactly the same expression.
Note when a simple let statement is used to assign functionality to an operator, it is valid only for the exact identifiers used. For the use of the let command to attach more general functionality to an operator, see forall.
Arrays as a whole cannot be arguments to let statements, but matrices as a whole can be legal arguments, provided both arguments are matrices. However, it is important to note that the two matrices are then linked. Any change to an element of one matrix changes the corresponding value in the other. Unless you want this behavior, you should not use let for matrices. The assignment operator assign can be used for non-tracking assignments, avoiding the side effects. Matrices are redimensioned as needed in let statements.
When array or matrix elements are used as the left-hand side of let statements, the contents of that element is used as the argument. When the contents is a number or some other expression that is not a valid left-hand side for let, you get an error message. If the contents is an identifier or simple expression, the let rule is globally attached to that identifier, and is in effect not only inside the array or matrix, but everywhere. Because of such unwanted side effects, you should not use let with array or matrix elements. The assignment operator := can be used to put values into array or matrix elements without the side effects.
Local variables declared inside begin...end blocks cannot be used as the left-hand side of let statements. However, begin...end blocks themselves can be used as the right-hand side of let statements. The construction:
for all<vars> let<operator>(<vars>)=<block>
is an alternative to the
procedure<name>(<vars>);<block>
construction. One important difference between the two constructions is that the <vars> as formal parameters to a procedure have their global values protected against change by the procedure, while the <vars> of a let statement are changed globally by its actions.
Be careful in using a construction such as let x = x + 1 except inside a controlled loop statement. The process of resubstitution continues until a stack overflow message is given.
The let statement may be used to make global changes to variables from inside procedures. If x is a formal parameter to a procedure, the command let x = ... makes the change to the calling variable. For example, if a procedure was defined by
procedure f(x,y); let x = 15;
and the procedure was called as
f(a,b);
awould have its value changed to 15. Be careful when using let statements inside procedures to avoid unwanted side effects.
It is also important to be careful when replacing let statements with other let statements. The overlapping of these substitutions can be unpredictable. Ordinarily the latest-entered rule is the first to be applied. Sometimes the previous rule is superseded completely; other times it stays around as a special case. The order of entering a set of related let expressions is very important to their eventual behavior. The best approach is to assume that the rules will be applied in an arbitrary order.