[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: The generality of define

 Date: 21 Apr 1986 09:43-PST
 From: andy@aids-unix (Andy Cromarty)
 Cc: rkirchne%carleton.csnet@CSNET-RELAY
 Subject: Re:  The generality of define

	"Although I knew that
	     (define (square x) (* x x))
	is equivalent to
	     (define square (lambda (x) (* x x))), ...."

Actually, a properly implemented

  (define (square x) (* x x))

is not equivalent to

  (define square (lambda (x) (* x x)))

at all, but rather to

  (define square (rec square (lambda (x) (* x x))))

The distinction between the rec and lambda forms is important during
definition of self-recursive procedures, as is noted (albeit somewhat
tersely) in the RRRS.  For example, consider

(define (fact1 n)
	(if (<? n 2)
	    (* n (fact1 (-1+ n)))))

(define copy1 fact1)

(define fact2
	 (lambda (n)
		 (if (<? n 2)
		     (* n (fact2 (-1+ n))))))

(define copy2 fact2)

Both fact1 and fact2 are definitions of factorial, and under
most circumstances there will be no difference between them.
If we subsequently redefine fact1 and fact2, however:

(define fact1 (lambda (x) x))		; For new fact1, just echo x back.
(define fact2 (lambda (x) x))		; Same thing for the new fact2.

then we get different results from copy1 and copy2:

(copy1 5) => 120		; i.e. 5!
(copy2 5) => 20			; i.e. same as "(* 5 ((lambda (x) x) 4))"

Since the implicit REC in the (fact1 n) definition in essence creates a
pointer to the fact1 procedure at the time of creation, the semantics
of that procedure becomes immune to subsequent changes in its own name.
In the case of fact2, the name wasn't "protected" by a REC, so copy2
calls the new fact2 procedure after fact2 has been redefined, rather
than the original fact2.  Obviously, both the REC and LAMBDA forms of
define can be useful, depending on the programmer's needs.