[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)
Subject: Re: The generality of define
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))))
(define (fact1 n)
(if (<? n 2)
1
(* n (fact1 (-1+ n)))))
(define fact2
(lambda (n)
(if (<? n 2)
1
(* n (fact2 (-1+ n))))))
asc
-------
In T there is *no* difference between these two forms (except that you
get a named-lambda in the first case rather than a lambda).
> (pp copy1)
(LAMBDA (N) (IF (<? N 2) 1 (* N (FACT1 (-1+ N))))) <<<<| Both closed
| in the same
> (pp copy2) | environment.
(LAMBDA (N) (IF (<? N 2) 1 (* N (FACT2 (-1+ N))))) <<<<|
> (copy1 5)
20
> (copy2 5)
20
This makes sense to me since (DEFINE (FOO ...) ...) is specified to
be equivalent to (DEFINE FOO (LAMBDA (...) ...)). In both cases, FOO is
defined to be a closure whose environment is the environment of definition,
i.e., the REPL-ENV.
To get the definition analogous to your REC case, you need to use LABELS
explicitly:
> (define fact3
(labels (((fact3 n) (if (< n 2) 1 (* n (fact3 (-1+ n))))))
fact3))
> (define copy3 fact3)
> (define fact3 (lambda (x) x))
> (copy3 5)
120
It might make more sense to make this the default expansion since you
would usually expect the recursive call to refer to the definition-time
procedure (as opposed to its "name"), though now the variables FACT3 and
N have different reference semantics within the same form. In the case of
two or more mutually recursive functions, you still have to rely on the
run-time values of the cells that the variables in the closure refer to
in the environment that the closure was defined in. It's debatable,
therefore, whether special reference semantics for the name of the lambda
form is the "proper implementation", though it does seem more natural
albeit hairier.
-- Ashwin.
-------