#lang racket
(require "4-2-3-lazy-lists-repl-program.rkt")
;;;;;;;;;;
;; 4.32 ;;
;;;;;;;;;;
;; The difference is that the car is lazy as well as the cdr. For example the book
;; example of integral and solve now works without having to delay the integrand.
;; Also, as the book mentions, if you implemented a binary tree as a cons of the left
;; branch with the right branch, you could now have lazy trees.
;;;;;;;;;;
;; 4.33 ;;
;;;;;;;;;;
;; The quoted clause in my-eval had to be changed to take the environment as a
;; parameter:
;; [(quoted? expr) (text-of-quotation expr env)]
;; text-of-quotation also had to be changed:
(define (list->lazy-list xs)
(if (empty? xs)
empty
(list 'my-cons
(first xs)
(list->lazy-list (rest xs)))))
(define (text-of-quotation expr env)
(define toq (second expr))
(if (pair? toq)
(my-eval (list->lazy-list toq) env)
toq))
;; text-of-quotation needs access to the environment because a lazy pair is
;; implemented as a compound procedure and compound procedures possess an enclosing
;; environment.
;;;;;;;;;;
;; 4.34 ;;
;;;;;;;;;;
;; A lazy list is an application of my-cons.
;; Change the definition of my-cons to use a distinctive parameter name:
'(define (my-cons x y)
(lambda (i-am-a-lazy-list)
(i-am-a-lazy-list x y)))
;; Now we have a way to recognize lazy-lists:
(define (lazy-list? obj)
(and (compound-procedure? obj)
(eq? (first (procedure-parameters obj))
'i-am-a-lazy-list)))
;; To select the my-car and my-cdr of a lazy list, look up x and y in the environment
;; of the lazy list. I got this idea from Felix021 on schemewiki.
(define (lazy-list-my-car lzl)
(force-it (lookup-variable-value 'x (procedure-environment lzl))))
(define (lazy-list-my-cdr lzl) ; never display this
(force-it (lookup-variable-value 'y (procedure-environment lzl))))
;; To make lazy-list-my-cdr work, I had to make the empty list self-evaluating:
(define (self-evaluating? expr)
(or (number? expr)
(string? expr)
(empty? expr)))
;; Now we can transfrom a lazy list into something printable:
(define (lazy-list->list lzl [num 10]) ; do not accumulate more than num elements
(define (loop acc rst n)
(cond [(zero? n) (reverse (cons '... acc))]
[(empty? rst) (reverse acc)]
[(self-evaluating? rst)
(reverse (cons rst (cons "." acc)))]
[else
(loop (cons (lazy-list-my-car rst) acc)
(lazy-list-my-cdr rst)
(sub1 n))]))
(loop empty lzl num))
;; Because of infinite lists, we terminate the display after at most ten elements.
;; Change user-print in repl operations to handle lazy lists:
(define (user-print object)
(cond [(lazy-list? object)
(displayln (lazy-list->list object))]
[(compound-procedure? object)
(displayln (list 'compound-procedure
(procedure-parameters object)
(procedure-body object)
'<procedure-env>))]
[else (displayln object)]))
;; (driver-loop)
;; ;;; L-Eval input:
;; '(1 2 3)
;; ;;; L-Eval value:
;; (1 2 3)
;; ;;; L-Eval input:
;; (my-cons 1 2)
;; ;;; L-Eval value:
;; (1 . 2)
;; ;;; L-Eval input:
;; '(1 2 3 4 5 6 7 8 9 10 11 12)
;; ;;; L-Eval value:
;; (1 2 3 4 5 6 7 8 9 10 ...)
;; ;;; L-Eval input:
;; '(1 "a" 23 "xyz")
;; ;;; L-Eval value:
;; (1 a 23 xyz)
;; ;;; L-Eval input:
;; (my-cons 1 "a")
;; ;;; L-Eval value:
;; (1 . a)
Comments
0 B
|👍
/👎
0 B
|👍
/👎