timothy235

sicp-4-2-3-streams-as-lazy-lists

Mar 19th, 2017
86
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Racket 3.55 KB | None | 0 0
  1. #lang racket
  2. (require "4-2-3-lazy-lists-repl-program.rkt")
  3.  
  4. ;;;;;;;;;;
  5. ;; 4.32 ;;
  6. ;;;;;;;;;;
  7.  
  8. ;; The difference is that the car is lazy as well as the cdr.  For example the book
  9. ;; example of integral and solve now works without having to delay the integrand.
  10.  
  11. ;; Also, as the book mentions, if you implemented a binary tree as a cons of the left
  12. ;; branch with the right branch, you could now have lazy trees.
  13.  
  14. ;;;;;;;;;;
  15. ;; 4.33 ;;
  16. ;;;;;;;;;;
  17.  
  18. ;; The quoted clause in my-eval had to be changed to take the environment as a
  19. ;; parameter:
  20.  
  21.         ;; [(quoted? expr) (text-of-quotation expr env)]
  22.  
  23. ;; text-of-quotation also had to be changed:
  24.  
  25. (define (list->lazy-list xs)
  26.   (if (empty? xs)
  27.     empty
  28.     (list 'my-cons
  29.           (first xs)
  30.           (list->lazy-list (rest xs)))))
  31.  
  32. (define (text-of-quotation expr env)
  33.   (define toq (second expr))
  34.   (if (pair? toq)
  35.     (my-eval (list->lazy-list toq) env)
  36.     toq))
  37.  
  38. ;; text-of-quotation needs access to the environment because a lazy pair is
  39. ;; implemented as a compound procedure and compound procedures possess an enclosing
  40. ;; environment.
  41.  
  42. ;;;;;;;;;;
  43. ;; 4.34 ;;
  44. ;;;;;;;;;;
  45.  
  46. ;; A lazy list is an application of my-cons.
  47.  
  48. ;; Change the definition of my-cons to use a distinctive parameter name:
  49.  
  50. '(define (my-cons x y)
  51.    (lambda (i-am-a-lazy-list)
  52.      (i-am-a-lazy-list x y)))
  53.  
  54. ;; Now we have a way to recognize lazy-lists:
  55.  
  56. (define (lazy-list? obj)
  57.   (and (compound-procedure? obj)
  58.        (eq? (first (procedure-parameters obj))
  59.             'i-am-a-lazy-list)))
  60.  
  61. ;; To select the my-car and my-cdr of a lazy list, look up x and y in the environment
  62. ;; of the lazy list.  I got this idea from Felix021 on schemewiki.
  63.  
  64. (define (lazy-list-my-car lzl)
  65.   (force-it (lookup-variable-value 'x (procedure-environment lzl))))
  66.  
  67. (define (lazy-list-my-cdr lzl) ; never display this
  68.   (force-it (lookup-variable-value 'y (procedure-environment lzl))))
  69.  
  70. ;; To make lazy-list-my-cdr work, I had to make the empty list self-evaluating:
  71.  
  72. (define (self-evaluating? expr)
  73.   (or (number? expr)
  74.       (string? expr)
  75.       (empty? expr)))
  76.  
  77. ;; Now we can transfrom a lazy list into something printable:
  78.  
  79. (define (lazy-list->list lzl [num 10]) ; do not accumulate more than num elements
  80.   (define (loop acc rst n)
  81.     (cond [(zero? n) (reverse (cons '... acc))]
  82.           [(empty? rst) (reverse acc)]
  83.           [(self-evaluating? rst)
  84.            (reverse (cons rst (cons "." acc)))]
  85.           [else
  86.             (loop (cons (lazy-list-my-car rst) acc)
  87.                   (lazy-list-my-cdr rst)
  88.                   (sub1 n))]))
  89.   (loop empty lzl num))
  90.  
  91. ;; Because of infinite lists, we terminate the display after at most ten elements.
  92.  
  93. ;; Change user-print in repl operations to handle lazy lists:
  94.  
  95. (define (user-print object)
  96.   (cond [(lazy-list? object)
  97.          (displayln (lazy-list->list object))]
  98.         [(compound-procedure? object)
  99.          (displayln (list 'compound-procedure
  100.                           (procedure-parameters object)
  101.                           (procedure-body object)
  102.                           '<procedure-env>))]
  103.         [else (displayln object)]))
  104.  
  105. ;; (driver-loop)
  106. ;; ;;; L-Eval input:
  107. ;; '(1 2 3)
  108. ;; ;;; L-Eval value:
  109. ;; (1 2 3)
  110. ;; ;;; L-Eval input:
  111. ;; (my-cons 1 2)
  112. ;; ;;; L-Eval value:
  113. ;; (1 . 2)
  114. ;; ;;; L-Eval input:
  115. ;; '(1 2 3 4 5 6 7 8 9 10 11 12)
  116. ;; ;;; L-Eval value:
  117. ;; (1 2 3 4 5 6 7 8 9 10 ...)
  118. ;; ;;; L-Eval input:
  119. ;; '(1 "a" 23 "xyz")
  120. ;; ;;; L-Eval value:
  121. ;; (1 a 23 xyz)
  122. ;; ;;; L-Eval input:
  123. ;; (my-cons 1 "a")
  124. ;; ;;; L-Eval value:
  125. ;; (1 . a)
Add Comment
Please, Sign In to add comment