52
(LAMBDA (A B C)
((LAMBDA (Q1 Q2 Q3)
(LIST (/ (+ Q1 Q2) Q3)
(/ (- Q1 Q2) Q3)))
(- B)
(SQRT (- (^ B 2) (* 4 A C)))
(* 2 A)))
(There would be no problem of conflicting names as there is for macro rules, because we are operating on code for which all variables have already been renamed; Q1, Q2, and Q3 can be chosen as the next variables in the renaming sequence.)
This approach doesn't always work if side-effects are present; the
abstracted (!) common subexpression may be evaluated too soon, or the wrong
number of times. This can be solved by wrapping (LAMBDA () ⭙) around the common
subexpression, and replacing references by a combination instead of a simple
variable reference. For example:
(IF (HAIRYP X)
(BLOCK (PRINT '|Here is some hair:|)
(PRINT X)
(PRINT '|End of hair.|))
(BLOCK (PRINT '|This one is bald:|)
(PRINT X)
(PRINT '|End of baldness.|)))
We could not transform it into this:
((LAMBDA (Q1)
(IF (HAIRYP X)
(BLOCK (PRINT '|Here is some hair:|)
Q1
(PRINT '|End of hair.|))
(BLOCK (PRINT '|This one is bald:|)
Q1
(PRINT '|End of baldness.|))))
(PRINT X))
because x would be printed before the appropriate leading message. Instead, we