Exercise 4.33: transform quoted pairs into cons for lazy lists

This turns a quoted expression into one or more conses.  If these are
defined to be the lazy versions, then we will get lazy lists.
This commit is contained in:
Oliver Payne 2023-09-09 23:19:11 +01:00
parent 01cb1c69dd
commit 51d71bbfb5
2 changed files with 68 additions and 5 deletions

View File

@ -22,7 +22,11 @@
(define (lazy-eval exp env)
(cond ((self-evaluating? exp) exp)
((variable? exp) (lookup-variable-value exp env))
((quoted? exp) (text-of-quotation exp))
((quoted? exp) (let ((text (text-of-quotation exp)))
(if (pair? text)
(lazy-eval (quoted-exp->cons-quoted text)
env)
text)))
((assignment? exp) (eval-assignment exp env lazy-eval))
((definition? exp) (eval-definition exp env lazy-eval))
((if? exp) (lazy-eval-if exp env))

View File

@ -1,25 +1,84 @@
#lang sicp
(#%provide (all-defined))
(#%require racket/trace)
(#%require racket/trace
rackunit
(only racket/base module+))
(trace-define (self-evaluating? exp)
(define (self-evaluating? exp)
(cond ((number? exp) true)
((string? exp) true)
((eq? exp '*unassigned*) true) ; Special symbol that can
; never be a variable.
(else false)))
(trace-define (quoted? exp)
(define (quoted? exp)
(tagged-list? exp 'quote))
(define (text-of-quotation exp) (cadr exp))
;; Exercise 4.33
;; Transform quoted list to (cons a (cons b ...)). This will be
;; evaluated by whichever version of cons (lazy or strict) is in scope
;; in the evaluator.
;; (quote (a b c)) -> (cons (quote a) (cons (quote b) (cons (quote c) (quote ()))))
;; (eval 'a) -> a
;; (eval '(a))
;; -> (eval `(cons ,(car '(a)) ,(cdr '(a))))
;; -> (eval (cons 'a '()))
;; (eval '(a . b))
;; -> (eval `(cons ,(car '(a . b)) ,(cdr '(a . b))))
;; -> (eval `(cons 'a 'b))
;; (eval '(a b))
;; -> (eval `(cons ,(car '(a b)) (cons ,(cadr '(a b)) ,(cdr (cdr '(a
;; b))))))
;; -> (eval `(cons 'a (cons 'b ())))
;; (eval '(a b))
;; -> (eval (eval-quoted '(a b)))
;; -> (eval `(cons 'a ,(eval-quoted '(b))))
;; -> (eval `(cons 'a (cons 'b ,eval-quoted('()))))
;; -> (eval `(cons 'a (cons 'b '())))
(define (quoted-exp->cons-quoted exp)
(cond ((null? exp) (list 'quote '()))
((pair? exp)
(list 'cons
(cond ((pair? (car exp))
(quoted-exp->cons-quoted (car exp)))
(else
(list 'quote (car exp))))
(quoted-exp->cons-quoted (cdr exp))))
(else (list 'quote exp))))
(module+ test
(check-equal? (quoted-exp->cons-quoted '(a b))
'(cons 'a (cons 'b '())))
(check-equal? (quoted-exp->cons-quoted '(a (b c) d))
'(cons 'a
(cons (cons 'b (cons 'c '()))
(cons 'd '()))))
(check-equal? (quoted-exp->cons-quoted '(a . b))
'(cons 'a 'b))
(check-equal? (quoted-exp->cons-quoted '((a . b) c))
'(cons (cons 'a 'b) (cons 'c '())))
(check-equal? (quoted-exp->cons-quoted '((a . b) . c))
'(cons (cons 'a 'b) 'c))
(check-equal? (quoted-exp->cons-quoted 'a)
(list 'quote 'a))
(check-equal? (quoted-exp->cons-quoted '1)
(list 'quote 1)))
(define (tagged-list? exp tag)
(if (pair? exp)
(eq? (car exp) tag)
false))
(trace-define (variable? exp) (symbol? exp))
(define (variable? exp) (symbol? exp))
;; Assignment
(define (assignment? exp)