Advertisement
timothy235

sicp-4-2-3-lazy-lists-repl-program

Mar 19th, 2017
152
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Racket 21.76 KB | None | 0 0
  1. #lang racket
  2. (require racket/mpair)
  3. (provide (all-defined-out))
  4.  
  5. ;; This is the repl program for section 4.2.3.  It implements lazy-lists by
  6. ;; installing the lazy compound procedures my-cons, my-car, and my-cdr.  Quotation
  7. ;; has been modified according to exercise 4.33 to produce lazy lists, and the driver
  8. ;; loop has been modified according to exercise 4.34 to make lazy lists print nicely.
  9. ;; Use "4-2-3-lazy-lists-repl-test.rkt" to test basic functionality.
  10.  
  11. ;; PROGRAM SECTIONS:
  12.  
  13. ;; 1. my-eval and my-apply
  14. ;; 2. eval procedures
  15. ;; 3. self-evaluating expressions, variables, and quotations
  16. ;; 4. definition and assignment
  17. ;; 5. thunks, lambdas, procedures and applications
  18. ;; 6. sequences and begin expressions
  19. ;; 7. boolean expressions
  20. ;; 8. if and cond expressions
  21. ;; 9. let, let*, and named-let
  22. ;; 10. environment and frames
  23. ;; 11. primitive procedures and the global environment
  24. ;; 12. repl operations
  25. ;; 13. lazy list operations
  26.  
  27. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  28. ;; 1. MY-EVAL AND MY-APPLY  ;;
  29. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  30.  
  31. (define (my-eval expr env)
  32.   (cond [(self-evaluating? expr) expr]
  33.         [(variable? expr) (lookup-variable-value expr env)]
  34.         [(quoted? expr) (text-of-quotation expr env)]
  35.         [(definition? expr) (eval-definition expr env)]
  36.         [(assignment? expr) (eval-assignment expr env)]
  37.         [(if? expr) (eval-if expr env)]
  38.         [(cond? expr) (my-eval (cond->if expr) env)]
  39.         [(begin? expr) (eval-sequence (begin-actions expr) env)]
  40.         [(and? expr) (eval-and expr env)]
  41.         [(or? expr) (eval-or expr env)]
  42.         [(let? expr) (my-eval (let->combination expr) env)]
  43.         [(let*? expr) (my-eval (let*->nested-lets expr) env)]
  44.         [(named-let? expr) (my-eval (named-let->sequence expr) env)]
  45.         [(lambda? expr)
  46.          (make-procedure (lambda-parameters expr)
  47.                          (lambda-body expr)
  48.                          env)]
  49.         [(application? expr)
  50.          (my-apply (actual-value (operator expr) env)
  51.                    (operands expr)
  52.                    env)]
  53.         [else (error "Unknown expression type -- MY-EVAL" expr)]))
  54.  
  55. (define (my-apply procedure arguments env)
  56.   (cond [(primitive-procedure? procedure)
  57.          (apply-primitive-procedure
  58.            procedure
  59.            (list-of-arg-values arguments env))]
  60.         [(compound-procedure? procedure)
  61.          (eval-sequence
  62.            (procedure-body procedure)
  63.            (extend-environment
  64.              (procedure-parameters procedure)
  65.              (list-of-delayed-args arguments env)
  66.              (procedure-environment procedure)))]
  67.         [else (error "Unknown procedure type -- APPLY" procedure)]))
  68.  
  69. ;;;;;;;;;;;;;;;;;;;;;;;;;
  70. ;; 2. EVAL PROCEDURES  ;;
  71. ;;;;;;;;;;;;;;;;;;;;;;;;;
  72.  
  73. (define (eval-definition expr env)
  74.   (define-variable! (definition-variable expr)
  75.                     (my-eval (definition-value expr) env)
  76.                     env)
  77.   'ok)
  78. (define (eval-assignment expr env)
  79.   (set-variable-value! (assignment-variable expr)
  80.                        (my-eval (assignment-value expr) env)
  81.                        env)
  82.   'ok)
  83. (define (list-of-values exprs env)
  84.   (if (no-operands? exprs)
  85.     empty
  86.     (cons (my-eval (first-operand exprs) env)
  87.           (list-of-values (rest-operands exprs) env))))
  88. (define (eval-sequence exprs env)
  89.   (cond [(last-exp? exprs) (my-eval (first-exp exprs) env)]
  90.         [else (my-eval (first-exp exprs) env)
  91.               (eval-sequence (rest-exps exprs) env)]))
  92. (define (eval-if expr env)
  93.   (if (true? (actual-value (if-predicate expr) env))
  94.     (my-eval (if-consequent expr) env)
  95.     (my-eval (if-alternative expr) env)))
  96. (define (eval-and expr env)
  97.   (define ops (and-operands expr))
  98.   (cond [(empty? ops) 'true] ; (and) should be true
  99.         [else
  100.           (define val (my-eval (first ops) env))
  101.           (define rest-ops (rest ops))
  102.           (cond [(empty? rest-ops) val] ; (and x) should be x
  103.                 [(false? val) false]
  104.                 [else
  105.                   (eval-and (make-and rest-ops) env)])]))
  106. (define (eval-or expr env)
  107.   (define ops (or-operands expr))
  108.   (cond [(empty? ops) 'false] ; (or) should be false
  109.         [else
  110.           (define val (my-eval (first ops) env))
  111.           (define rest-ops (rest ops))
  112.           (cond [(empty? rest-ops) val] ; (or x) should be x
  113.                 [(not (false? val)) val]
  114.                 [else
  115.                   (eval-or (make-or rest-ops) env)])]))
  116.  
  117. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  118. ;; 3. SELF-EVALUATING EXPRESSIONS, VARIABLES, AND QUOTATIONS  ;;
  119. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  120.  
  121. (define (tagged-list? expr tag)
  122.   (or (and (pair? expr) (eq? (first expr) tag))
  123.       (and (mpair? expr) (eq? (mcar expr) tag))))
  124. ;; Only numbers and strings are self-evaluating.
  125. (define (self-evaluating? expr)
  126.   (or (number? expr)
  127.       (string? expr)))
  128. (define (variable? expr)
  129.   (symbol? expr))
  130. ;; Quotations have the form:  (quote <text-of-quotation>)
  131. (define (quoted? expr)
  132.   (tagged-list? expr 'quote))
  133. (define (text-of-quotation expr env)
  134.   (define toq (second expr))
  135.   (if (pair? toq)
  136.     (my-eval (list->lazy-list toq) env)
  137.     toq))
  138.  
  139. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  140. ;; 4. DEFINITION AND ASSIGNMENT  ;;
  141. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  142.  
  143. ;; Variable definitions have the form:  (define <var> <value>)
  144.  
  145. ;; Procedure definitions have the form:
  146. ;; (define (<var> <parameter-1> ... <parameter-n>) <body>)
  147. ;; which is equivalent to:
  148. ;; (define <var> (lambda (<parameter-1> ... <parameter-n>) <body>))
  149.  
  150. (define (definition? expr) (tagged-list? expr 'define))
  151. (define (definition-variable expr)
  152.   (if (symbol? (second expr))
  153.     (second expr)
  154.     (first (second expr))))
  155. (define (definition-value expr)
  156.   (if (symbol? (second expr))
  157.     (third expr)
  158.     (make-lambda (rest (second expr)) ; formal parameters
  159.                  (drop expr 2))))
  160.  
  161. ;; Assignments have the form:  (set! <var> <value>)
  162. (define (assignment? expr)
  163.   (tagged-list? expr 'set!))
  164. (define (assignment-variable expr) (second expr))
  165. (define (assignment-value expr) (third expr))
  166.  
  167. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  168. ;; 5. THUNKS, LAMBDAS, PROCEDURES AND APPLICATIONS  ;;
  169. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  170.  
  171. (define (thunk? obj) (tagged-list? obj 'thunk))
  172. (define (thunk-exp my-thunk) (mcar (mcdr my-thunk)))
  173. (define (thunk-env my-thunk) (mcar (mcdr (mcdr my-thunk))))
  174. (define (delay-it expr env)
  175.   (mlist 'thunk expr env))
  176. (define (evaluated-thunk? obj) (tagged-list? obj 'evaluated-thunk))
  177. (define (thunk-value evaluated-thunk) (mcar (mcdr evaluated-thunk)))
  178. (define (force-it obj)
  179.   (cond [(thunk? obj)
  180.          (define result (actual-value (thunk-exp obj) (thunk-env obj)))
  181.          (set-mcar! obj 'evaluated-thunk)
  182.          (set-mcar! (mcdr obj) result)
  183.          (set-mcdr! (mcdr obj) empty)
  184.          result]
  185.         [(evaluated-thunk? obj) (thunk-value obj)]
  186.         [else obj]))
  187.  
  188. ;; Lambda expressions have the form:
  189. ;; (lambda (<parameters>) <body>)
  190. (define (lambda? expr) (tagged-list? expr 'lambda))
  191. (define (lambda-parameters expr) (second expr))
  192. (define (lambda-body expr) (drop expr 2))
  193. (define (make-lambda parameters body)
  194.   (cons 'lambda (cons parameters body)))
  195.  
  196. ;; Procedures:
  197. (define (make-procedure parameters body env)
  198.   (list 'procedure parameters body env))
  199. (define (compound-procedure? p)
  200.   (tagged-list? p 'procedure))
  201. (define (procedure-parameters p) (second p))
  202. (define (procedure-body p) (third p))
  203. (define (procedure-environment p) (fourth p))
  204.  
  205. ;; Procedure applications have the from:
  206. ;; (<var> <parameter> ...)
  207. (define (application? expr) (pair? expr))
  208. (define (operator expr) (first expr))
  209. (define (operands expr) (rest expr))
  210. (define (no-operands? ops) (empty? ops))
  211. (define (first-operand ops) (first ops))
  212. (define (rest-operands ops) (rest ops))
  213. (define (actual-value expr env)
  214.   (force-it (my-eval expr env)))
  215. (define (list-of-arg-values exprs env)
  216.   (if (no-operands? exprs)
  217.     empty
  218.     (cons (actual-value (first-operand exprs) env)
  219.           (list-of-arg-values (rest-operands exprs)
  220.                               env))))
  221. (define (list-of-delayed-args exprs env)
  222.   (if (no-operands? exprs)
  223.     empty
  224.     (cons (delay-it (first-operand exprs) env)
  225.           (list-of-delayed-args (rest-operands exprs)
  226.                                 env))))
  227.  
  228. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  229. ;; 6. SEQUENCES AND BEGIN EXPRESSIONS  ;;
  230. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  231.  
  232. ;; Begin has the form:  (begin <actions>)
  233. (define (begin? expr) (tagged-list? expr 'begin))
  234. (define (begin-actions expr) (rest expr))
  235. (define (last-exp? seq) (empty? (rest seq)))
  236. (define (first-exp seq) (first seq))
  237. (define (rest-exps seq) (rest seq))
  238. (define (sequence->exp seq)
  239.   (cond [(empty? seq) seq]
  240.         [(last-exp? seq) (first-exp seq)]
  241.         [else (make-begin seq)]))
  242. ;; begin constructor used by cond->if
  243. (define (make-begin seq) (cons 'begin seq))
  244.  
  245. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  246. ;; 7. BOOLEAN EXPRESSIONS  ;;
  247. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  248.  
  249. (define (true? x) (not (false? x)))
  250. (define (and? expr) (tagged-list? expr 'and))
  251. (define (and-operands expr) (rest expr))
  252. (define (make-and sequence) (cons 'and sequence))
  253. (define (or? expr) (tagged-list? expr 'or))
  254. (define (or-operands expr) (rest expr))
  255. (define (make-or sequence) (cons 'or sequence))
  256.  
  257. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  258. ;; 8. IF AND COND EXPRESSIONS  ;;
  259. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  260.  
  261. ;; Conditionals have the form:  (if <predicate> <consequent> <alternative>)
  262. ;; If no alternative, use false.
  263. (define (if? expr) (tagged-list? expr 'if))
  264. (define (if-predicate expr) (second expr))
  265. (define (if-consequent expr) (third expr))
  266. (define (if-alternative expr)
  267.   (if (not (empty? (drop expr 3)))
  268.     (fourth expr)
  269.     'false))
  270. (define (make-if predicate consequent alternative)
  271.   (list 'if predicate consequent alternative))
  272.  
  273. ;; Cond has the form:
  274. ;; (cond ((<predicate> <actions>)
  275.        ;; (else <actions>))) ; if no else, assume (else false) clause
  276. (define (cond? expr) (tagged-list? expr 'cond))
  277. (define (cond-clauses expr) (rest expr))
  278. ;; regular cond clause
  279. (define (cond-predicate clause) (first clause))
  280. (define (cond-actions clause) (rest clause))
  281. ;; alternate test clause
  282. (define (cond-alternate-clause? clause)
  283.   (eq? (second clause) '=>))
  284. (define (cond-test clause) (first clause))
  285. (define (cond-recipient clause) (third clause))
  286. ;; else clause
  287. (define (cond-else-clause? clause)
  288.   (eq? (cond-predicate clause) 'else))
  289. ;; derive cond from if
  290. (define (cond->if expr)
  291.   (expand-clauses (cond-clauses expr)))
  292. (define (expand-clauses clauses)
  293.   (cond [(empty? clauses) 'false] ; no else clause
  294.         [else
  295.           (define first-clause (first clauses))
  296.           (define rest-clauses (rest clauses))
  297.           (cond [(cond-else-clause? first-clause)
  298.                  (if (empty? rest-clauses)
  299.                    (sequence->exp (cond-actions first-clause))
  300.                    (error "ELSE clause isn't last -- COND->IF" clauses))]
  301.                 [(cond-alternate-clause? first-clause)
  302.                  (define test (cond-test first-clause)) ; gets evaluated twice
  303.                  (make-if test
  304.                           (list (cond-recipient first-clause)
  305.                                 test)
  306.                           (expand-clauses rest-clauses))]
  307.                 [else
  308.                   (make-if (cond-predicate first-clause)
  309.                            (sequence->exp (cond-actions first-clause))
  310.                            (expand-clauses rest-clauses))])]))
  311.  
  312. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  313. ;; 9. LET, LET*, AND NAMED-LET  ;;
  314. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  315.  
  316. ;; Let has the form:  (let (<bindings>) <body>)
  317. (define (let? expr)
  318.   (and (tagged-list? expr 'let)
  319.        (list? (second expr))))
  320. (define (let-bindings expr) (second expr))
  321. (define (let-parameters expr) (map first (let-bindings expr)))
  322. (define (let-expressions expr) (map second (let-bindings expr)))
  323. (define (let-body expr) (drop expr 2))
  324. (define (let->combination expr)
  325.   (cond [(empty? (let-bindings expr)) ; do not unnecessarily lambda wrap
  326.          (sequence->exp (let-body expr))]
  327.         [else
  328.           (cons (make-lambda (let-parameters expr)
  329.                              (let-body expr))
  330.                 (let-expressions expr))]))
  331. (define (make-let bindings body)
  332.   (cons 'let (cons bindings body)))
  333.  
  334. ;; Let* has the same form as let, but bindings are sequential.
  335. (define (let*? expr) (tagged-list? expr 'let*))
  336. (define (let*-bindings expr) (second expr))
  337. (define (let*-body expr) (drop expr 2))
  338. (define (make-let* bindings body)
  339.   (cons 'let* (cons bindings body)))
  340. (define (let*->nested-lets expr)
  341.   (define bindings (let*-bindings expr))
  342.   (cond [(empty? bindings)
  343.          (sequence->exp (let-body expr))]
  344.         [else
  345.           (list 'let
  346.                 (list (first bindings))
  347.                 (let*->nested-lets
  348.                   (make-let* (rest bindings)
  349.                              (let-body expr))))]))
  350.  
  351. ;; Named-let has the form:  (let <name> (<bindings>) <body>)
  352. (define (named-let? expr)
  353.   (and (tagged-list? expr 'let)
  354.        (not (list? (second expr)))))
  355. (define (named-let-name expr) (second expr))
  356. (define (named-let-bindings expr) (third expr))
  357. (define (named-let-parameters expr) (map first (named-let-bindings expr)))
  358. (define (named-let-expressions expr) (map second (named-let-bindings expr)))
  359. (define (named-let-body expr) (drop expr 3))
  360. (define (named-let->sequence expr)
  361.   (define bindings (named-let-bindings expr))
  362.   (cond [(empty? bindings)
  363.          (sequence->exp (named-let-body expr))]
  364.         [else
  365.           (list 'begin
  366.                 (cons 'define ; first define the named function
  367.                       (cons (cons (named-let-name expr)
  368.                                   (named-let-parameters expr))
  369.                             (named-let-body expr)))
  370.                 (cons (named-let-name expr) ; then apply it to the expressions
  371.                       (named-let-expressions expr)))]))
  372.  
  373. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  374. ;; 10. ENVIRONMENT AND FRAMES  ;;
  375. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  376.  
  377. ;; An environment is a mutable list of frames.  The enclosing environment is the mcdr
  378. ;; of the list.  A frame is a mutable list of bindings with a 'frame header.  A
  379. ;; binding is a var-val pair ie (mcons var val).
  380.  
  381. ;; Environments support four procedures:
  382.     ;; lookup-variable-value
  383.     ;; extend-environment
  384.     ;; define-variable
  385.     ;; set-variable-value
  386.  
  387. ;; Two helper functions support the environment procedures:
  388.     ;; find-binding-in-frame
  389.     ;; find-binding-in-environment
  390.  
  391. (define (enclosing-environment env) (mcdr env))
  392. (define (first-frame env) (mcar env))
  393. (define the-empty-environment empty)
  394. (define the-empty-frame (mlist 'frame))
  395. (define (empty-frame? frame)
  396.   (empty? (frame-bindings frame)))
  397. (define (make-frame vars vals)
  398.   (mcons 'frame
  399.          (mmap mcons
  400.                (list->mlist vars)
  401.                (list->mlist vals))))
  402. (define (frame-bindings frame) (mcdr frame))
  403. (define (frame-variables frame) (mmap mcar (frame-bindings frame)))
  404. (define (frame-values frame) (mmap mcdr (frame-bindings frame)))
  405.  
  406. (define (binding-variable binding) (mcar binding))
  407. (define (binding-value binding) (mcdr binding))
  408. (define (set-value! binding val) (set-mcdr! binding val))
  409. (define (add-binding-to-frame! var val frame)
  410.   (mappend! frame (mlist (mcons var val))))
  411. (define (find-binding-in-frame var frame)
  412.   ; Return the var-val pair if present else false.
  413.   (define (loop bindings)
  414.     (cond [(empty? bindings) false]
  415.           [else
  416.             (define b (mcar bindings))
  417.             (if (eq? var (binding-variable b))
  418.               b
  419.               (loop (mcdr bindings)))]))
  420.   (loop (frame-bindings frame)))
  421. (define (find-binding-in-env var env)
  422.   ; Return the closest binding for var if present else false.
  423.   (cond [(eq? env the-empty-environment) false]
  424.         [else
  425.           (define b (find-binding-in-frame var (first-frame env)))
  426.           (or b (find-binding-in-env var (enclosing-environment env)))]))
  427.  
  428. (define (lookup-variable-value var env)
  429.   (define b (find-binding-in-env var env))
  430.   (if b
  431.     (binding-value b)
  432.     (error "Unbound variable" var)))
  433. (define (extend-environment vars vals base-env)
  434.   (cond [(= (length vars) (length vals))
  435.          (mcons (make-frame vars vals) base-env)]
  436.         [else
  437.           (if (< (length vars) (length vals))
  438.             (error "Too many arguments supplied" vars vals)
  439.             (error "Too few arguments supplied" vars vals))]))
  440. (define (define-variable! var val env)
  441.   (define frame (first-frame env))
  442.   (define b (find-binding-in-frame var frame))
  443.   (if b
  444.     (set-value! b val)
  445.     (add-binding-to-frame! var val frame)))
  446. (define (set-variable-value! var val env)
  447.   (define b (find-binding-in-env var env))
  448.   (if b
  449.     (set-value! b val)
  450.     (error "Unbound variable -- SET!" var)))
  451.  
  452. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  453. ;; 11. PRIMITIVE PROCEDURES AND THE GLOBAL ENVIRONMENT  ;;
  454. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  455.  
  456. (define primitive-procedures
  457.   (list
  458.     (list 'cons cons)
  459.     (list 'car car)
  460.     (list 'cdr cdr)
  461.     (list '+ +)
  462.     (list '* *)
  463.     (list '- -)
  464.     (list '< <)
  465.     (list '> >)
  466.     (list '<= <=)
  467.     (list '>= >=)
  468.     (list '= =)
  469.     (list 'not not)
  470.     (list 'false? false?)
  471.     (list 'true? (lambda (x) (not (false? x))))
  472.     (list 'empty? empty?)
  473.     (list 'equal? equal?)
  474.     (list 'displayln displayln)
  475.     (list 'list list)
  476.     ))
  477. (define (primitive-procedure? proc)
  478.   (tagged-list? proc 'primitive))
  479. (define (primitive-implementation proc)
  480.   (second proc))
  481. (define (primitive-procedure-names)
  482.   (map first primitive-procedures))
  483. (define (primitive-procedure-objects)
  484.   (map (lambda (proc) (list 'primitive (second proc)))
  485.        primitive-procedures))
  486. (define apply-in-underlying-scheme apply)
  487. ;; The metacircular evaluator's apply is my-apply.
  488. (define (apply-primitive-procedure proc args)
  489.   (apply-in-underlying-scheme
  490.     (primitive-implementation proc) args))
  491.  
  492. (define (setup-environment)
  493.   (define initial-env
  494.     (extend-environment (primitive-procedure-names)
  495.                         (primitive-procedure-objects)
  496.                         the-empty-environment))
  497.   (define-variable! 'true true initial-env)
  498.   (define-variable! 'false false initial-env)
  499.   initial-env)
  500. (define the-global-environment (setup-environment))
  501.  
  502. ;;;;;;;;;;;;;;;;;;;;;;;;;;
  503. ;; 12. REPL OPERATIONS  ;;
  504. ;;;;;;;;;;;;;;;;;;;;;;;;;;
  505.  
  506. (define input-prompt ";;; L-Eval input:")
  507. (define output-prompt ";;; L-Eval value:")
  508. (define (driver-loop)
  509.   (prompt-for-input input-prompt)
  510.   (let* ([input (read)]
  511.          [output (actual-value input the-global-environment)])
  512.     (announce-output output-prompt)
  513.     (user-print output))
  514.   (driver-loop))
  515. (define prompt-for-input displayln)
  516. (define announce-output displayln)
  517. (define (user-print object)
  518.   (cond [(lazy-list? object)
  519.          (displayln (lazy-list->list object))]
  520.         [(compound-procedure? object)
  521.          (displayln (list 'compound-procedure
  522.                           (procedure-parameters object)
  523.                           (procedure-body object)
  524.                           '<procedure-env>))]
  525.         [else (displayln object)]))
  526.  
  527. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  528. ;; 13. LAZY LIST OPERATIONS ;;
  529. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  530.  
  531. (define (lazy-list? obj)
  532.   (and (compound-procedure? obj)
  533.        (eq? (first (procedure-parameters obj))
  534.             'i-am-a-lazy-list)))
  535. (define (lazy-list-my-car lzl)
  536.   (force-it (lookup-variable-value 'x (procedure-environment lzl))))
  537. (define (lazy-list-my-cdr lzl) ; never display this
  538.   (force-it (lookup-variable-value 'y (procedure-environment lzl))))
  539. (define (lazy-list->list lzl [num 10]) ; do not accumulate more than num elements
  540.   (define (loop acc rst n)
  541.     (cond [(zero? n) (reverse (cons '... acc))]
  542.           [(empty? rst) (reverse acc)]
  543.           [(self-evaluating? rst)
  544.            (reverse (cons rst (cons "." acc)))]
  545.           [else
  546.             (loop (cons (lazy-list-my-car rst) acc)
  547.                   (lazy-list-my-cdr rst)
  548.                   (sub1 n))]))
  549.   (loop empty lzl num))
  550. (define (list->lazy-list xs)
  551.   (if (empty? xs)
  552.     empty
  553.     (list 'my-cons
  554.           (first xs)
  555.           (list->lazy-list (rest xs)))))
  556.  
  557. ;; Add these definitions to the global environment:
  558. (define lazy-list-definitions
  559.   (list
  560.     '(define (my-cons x y)
  561.        (lambda (i-am-a-lazy-list)
  562.          (i-am-a-lazy-list x y)))
  563.     '(define (my-car z)
  564.        (z (lambda (p q) p)))
  565.     '(define (my-cdr z)
  566.        (z (lambda (p q) q)))
  567.     '(define (my-list-ref items n)
  568.        (if (= n 0)
  569.          (my-car items)
  570.          (my-list-ref (my-cdr items) (- n 1))))
  571.     '(define (my-map proc items)
  572.        (if (empty? items)
  573.         empty
  574.          (my-cons (proc (my-car items))
  575.                   (my-map proc (my-cdr items)))))
  576.     '(define (scale-list items factor)
  577.        (my-map (lambda (x) (* x factor))
  578.                items))
  579.     '(define (add-lists list1 list2)
  580.        (cond [(empty? list1) list2]
  581.              [(empty? list2) list1]
  582.              [else (my-cons (+ (my-car list1) (my-car list2))
  583.                             (add-lists (my-cdr list1) (my-cdr list2)))]))
  584.     '(define ones (my-cons 1 ones))
  585.     '(define integers (my-cons 1 (add-lists ones integers)))
  586.     '(define (integral integrand initial-value dt)
  587.        (define int
  588.          (my-cons initial-value
  589.                   (add-lists (scale-list integrand dt)
  590.                              int)))
  591.        int)
  592.     '(define (solve f y0 dt)
  593.        (define y (integral dy y0 dt))
  594.        (define dy (my-map f y))
  595.        y)
  596.     ))
  597. (define (install-lazy-list-definitions)
  598.   (for ([e lazy-list-definitions])
  599.     (my-eval e the-global-environment)))
  600. (install-lazy-list-definitions)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement