Fix bug where lazy pairs used excessive amounts of memory
This change makes cons a procedure created at startup, capturing the environment once rather than each time a pair is created.
This commit is contained in:
parent
a358de17d3
commit
255723b1fe
|
@ -6,8 +6,21 @@
|
|||
(#%provide lazy-lists-program)
|
||||
|
||||
(define lazy-lists-program
|
||||
'((define (cons x y)
|
||||
(lambda (m) (m x y)))
|
||||
'(
|
||||
;; The cons procedure needs to be created once at interpreter
|
||||
;; start up. This ensures that it captures only the initial
|
||||
;; environment. Then when it is called, that environment is
|
||||
;; extended to bind its parameters to the inputs.
|
||||
;; Specifically, it doesn't capture the whole environment at
|
||||
;; the call site of cons. The latter is what happens if we
|
||||
;; create the procedure at the call site. This leads to
|
||||
;; excessive memory use.
|
||||
;; lazy-lambda-pair produces a specially tagged procedure that is
|
||||
;; recognised as a lazy pair by the evaluator but is otherwise
|
||||
;; just a normal procedure.
|
||||
(define cons
|
||||
(lambda (x y)
|
||||
(lazy-pair-lambda (m) (m x y))))
|
||||
|
||||
(define (car z)
|
||||
(z (lambda (p q) p)))
|
||||
|
|
|
@ -35,12 +35,13 @@
|
|||
(make-procedure (lambda-parameters exp)
|
||||
(lambda-body exp)
|
||||
env))
|
||||
((lazy-pair-lambda? exp)
|
||||
(make-lazy-pair-procedure (lambda-parameters exp)
|
||||
(lambda-body exp)
|
||||
env))
|
||||
((begin? exp)
|
||||
(eval-sequence (begin-actions exp) env lazy-eval))
|
||||
((cond? exp) (lazy-eval (cond->if exp) env))
|
||||
((cons? exp) (eval-cons (cons-first-exp exp)
|
||||
(cons-second-exp exp)
|
||||
env))
|
||||
((application? exp) ; clause from book
|
||||
(lazy-apply (actual-value (operator exp) env)
|
||||
(operands exp)
|
||||
|
@ -57,6 +58,7 @@
|
|||
procedure
|
||||
(list-of-arg-values arguments env))) ; changed
|
||||
((lazy-pair? procedure)
|
||||
;; Skip over the lazy-pair tag if we have a lazy-pair as a procedure
|
||||
(lazy-apply (lazy-pair-proc procedure)
|
||||
arguments env))
|
||||
((compound-procedure? procedure)
|
||||
|
@ -95,12 +97,12 @@
|
|||
|
||||
|
||||
(define (user-print object env)
|
||||
(cond ((compound-procedure? object)
|
||||
(cond ((lazy-pair? object) (display (print-lazy-pair object env)))
|
||||
((compound-procedure? object)
|
||||
(display (list 'compound-procedure
|
||||
(procedure-parameters object)
|
||||
(procedure-body object)
|
||||
'<procedure-env>)))
|
||||
((lazy-pair? object) (display (print-lazy-pair object env)))
|
||||
(else (display object))))
|
||||
|
||||
(define (print-lazy-pair lazy-pair env)
|
||||
|
|
|
@ -112,6 +112,9 @@
|
|||
(define (make-lambda parameters body)
|
||||
(cons 'lambda (cons parameters body)))
|
||||
|
||||
;; Lazy-pair lambda is used to model lazy pairs
|
||||
(define (lazy-pair-lambda? exp) (tagged-list? exp 'lazy-pair-lambda))
|
||||
|
||||
;; if
|
||||
(define (if? exp) (tagged-list? exp 'if))
|
||||
(define (if-predicate exp) (cadr exp))
|
||||
|
@ -384,6 +387,10 @@
|
|||
(define (compound-procedure? p)
|
||||
(tagged-list? p 'procedure))
|
||||
|
||||
;; Lazy-pair procedure is a normal procedure tagged with lazy-pair to
|
||||
;; distinguish lazy pairs from procedures
|
||||
(define (make-lazy-pair-procedure parameters body env)
|
||||
(make-lazy-pair (make-procedure parameters body env)))
|
||||
|
||||
(define (procedure-parameters p) (cadr p))
|
||||
(define (procedure-body p) (caddr p))
|
||||
|
|
Loading…
Reference in New Issue