Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #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)
Add Comment
Please, Sign In to add comment