Steele and Sussman | March 10, 1976 | 7 | LAMBDA: The Ultimate Imperative |
write:
(LABELS ((L1 (LAMBDA ()
(IF B1 (L2)
(BLOCK S1
(IF B2 (L2)
(BLOCK S2 (L1)))))))
(L2 (LAMBDA () S3)))
(L1))
As with the DO
loop, this transformation depends critically on SCHEME's treatment of tail-recursion and on lexical scoping of variables. The labels are names of functions of no arguments. In order to "go to" the labeled code, we merely call the function named by that label.
Simple Assignment
Of course, all this sequencing of statements is useless unless the statements have side effects. An important side effect is assignment. For example, one often uses assignment to place intermediate results in a named location (i.e. a variable) so that they may be used more than once later without recomputing them:
begin
real a2, sqrtdisc;
a2 := 2*a;
sqrtdisc := sqrt(b↑2 - 4*a*c);
root1 := (- b + sqrtdisc) / a2;
root2 := (- b - sqrtdisc) / a2;
print(root1);
print(root2);
print(root1 + root2);
end
It is well known that such naming of intermediate results may be accomplished by calling a function and binding the formal parameter variables to the results:
((LAMBDA (A2 SQRTDISC)
((LAMBDA (ROOT1 ROOT2)
(BLOCK (PRINT ROOT1)
(PRINT ROOT2)
(PRINT (+ ROOT1 ROOT2))))
(/ (+ (- B) SQRTDISC) A2)
(/ (- (- B) SQRTDISC) A2)))
(* 2 A)
(SQRT (- (↑ B 2) (* 4 A C))))
This technique can be extended to handle all simple variable assignments which