Implement till 4.7

main
Felix Martin 2021-01-18 06:45:29 -05:00
parent c958d52f50
commit dd2002783e
1 changed files with 41 additions and 26 deletions

View File

@ -52,6 +52,7 @@
(put 'begin (lambda (exp env) (eval-sequence (begin-actions exp) env)))
(put 'cond (lambda (exp env) (eval (cond->if exp) env)))
(put 'let (lambda (exp env) (eval (let->lambda exp) env)))
(put 'let* (lambda (exp env) (eval (let*->nested-lets exp) env)))
(put 'and (lambda (exp env) (eval-and (clauses exp) env)))
(put 'or (lambda (exp env) (eval-or (clauses exp) env)))
(display "[install-eval-package]\n")
@ -103,18 +104,6 @@
(display "\nex-4.5 - modified-cond\n")
; Exercise 4.5. Scheme allows an additional syntax for cond clauses, (<test> =>
; <recipient>).
; If <test> evaluates to a true value, then <recipient> is evaluated. Its value
; must be a procedure of one argument; this procedure is then invoked on the
; value of the <test>, and the result is returned as the value of the cond
; expression. For example
; (cond ((assoc 'b '((a 1) (b 2))) => cadr)
; (else false))
; returns 2. Modify the handling of cond so that it supports this extended syntax.
(define (cond-test exp) (car exp))
(define (cond-recipient exp) (caddr exp))
(define (cond-test-recipient-clause? exp)
@ -143,23 +132,49 @@
(display "[done]\n")
(display "\nex-4.6 - let-expression\n")
(display "\nex-4.6 - let\n")
(define (let->lambda exp) 0)
(define (let? exp) (tagged-list exp 'let))
(define (let-init exp) (cadr exp))
(define (let-body exp) (cddr exp))
(define (let-init-var init) (car init))
(define (let-init-exp init) (cadr init))
(define (let-init-vars exp) (map let-init-var (let-init exp)))
(define (let-init-exps exp) (map let-init-exp (let-init exp)))
; (let ((<var1> <exp1>) ... (<varn> <expn>))
; <body>)
;
; ((lambda (<var1> ... <varn>)
; <body>)
; <exp1>
;
; <expn>)
(define (let->lambda exp)
(let ((let-variables (let-init-vars exp))
(let-expressions (let-init-exps exp)))
(cons (make-lambda let-variables (let-body exp))
let-expressions)))
; Implement a syntactic transformation let->combination that reduces evaluating
; let expressions to evaluating combinations of the type shown above, and add the
; appropriate clause to eval to handle let expressions
(assert (let->lambda '(let ((a 3) (b 4)) (* 3 a b)))
'((lambda (a b) (* 3 a b)) 3 4))
(display "\nex-4.7 - let*\n")
(define (let*? exp) (tagged-list exp 'let*))
(define (let*-inits exp) (cadr exp))
(define (let*-body exp) (cddr exp))
(define (let*-inits-empty? inits) (null? inits))
(define (let*-first-init inits) (car inits))
(define (let*-rest-init inits) (cdr inits))
(define (let*->nested-lets exp)
(define (nest-lets inits)
(if (let*-inits-empty? inits)
(sequence->exp (let*-body exp))
(list
'let
(list (let*-first-init inits))
(nest-lets (let*-rest-init inits)))))
(nest-lets (let*-inits exp)))
(assert (let*->nested-lets '(let* ((x 1) (y 2)) (* x y) (+ x y)))
'(let ((x 1)) (let ((y 2)) (begin (* x y) (+ x y)))))
(display "\nex-4.8 - named-let\n")
(display "\nex-4.7")
(display "\nex-4.9\n")