--- /dev/null
+#lang racket
+
+(define (cond? exp) (tagged-list? exp 'cond))
+(define (cond-clauses exp) (cdr exp))
+(define (cond-else-clause? clause)
+ (eq? (cond-predicate clause) 'else))
+(define (cond-predicate clause) (car clause))
+
+(define (cond-arrow-clause? clause) (eq? (cadr (cond-actions clause)) '=>))
+(define (cond-arrow-clause-recipient clause) (caddr clause))
+(define (cond-actions clause)
+ (if (cond-arrow-clause? clause)
+ (apply (cond-arrow-clause-recipient clause) (cond-predicate clause))
+ (cdr clause)))
+
+(define (cond->if exp)
+ (expand-clauses (cond-clauses exp)))
+
+(define (expand-clauses clauses)
+ (if (null? clauses)
+ 'false ; no else clause
+ (let ((first (car clauses))
+ (rest (cdr clauses)))
+ (if (cond-else-clause? first)
+ (if (null? rest)
+ (sequence->exp (cond-actions first))
+ (error "ELSE clause isn't last -- COND->IF"
+ clauses))
+ (make-if (cond-predicate first)
+ (sequence->exp (cond-actions first))
+ (expand-clauses rest))))))
\ No newline at end of file
--- /dev/null
+#lang racket/base
+
+(provide let->combination)
+
+(define (tagged-list? exp tag)
+ (if (pair? exp)
+ (eq? (car exp) tag)
+ #f))
+
+
+(define (make-lambda params body)
+ (cons 'lambda (cons params body)))
+
+(define (let? expr)
+ (tagged-list? expr 'let))
+
+(define (let-bindings expr) (cadr expr))
+(define (let-bindings-variables bindings) (map car bindings))
+(define (let-bindings-values bindings) (map cadr bindings))
+(define (let-body expr) (cddr expr))
+
+(define (let->combination expr)
+ (let ([bindings (let-bindings expr)])
+ (let ([vars (let-bindings-variables bindings)]
+ [vals (let-bindings-values bindings)]
+ [body (let-body expr)])
+ (cons (make-lambda vars body) vals))))
+
+(define ns (make-base-namespace))
+(eval (let->combination '(let ((x 2) (y 3)) (+ x y))) ns)
--- /dev/null
+#lang racket
+
+(define (tagged-list? exp tag)
+ (if (pair? exp)
+ (eq? (car exp) tag)
+ #f))
+
+(define (make-lambda params body)
+ (cons 'lambda (cons params body)))
+
+(define (let*? expr)
+ (tagged-list? expr 'let*))
+
+(define (let*-bindings expr) (cadr expr))
+(define (let*-body expr) (cddr expr))
+
+
+(define (let*->let bindings body)
+ (cond [(empty? bindings) '()]
+ [else
+ (let ([binding (car bindings)]
+ [rest-bindings (cdr bindings)])
+ (if (empty? rest-bindings)
+ (cons 'let (cons (list binding) body))
+ (cons 'let (cons (list binding) (list (let*->let rest-bindings body))))))]))
+
+#|
+
+(define (make-let bindings body)
+ (cons 'let (cons bindings body)))
+
+(define (let*->let bindings body)
+ (cond [(empty? bindings) body]
+ [else
+ (make-let (list (car bindings))
+ (list (let*->let (cdr bindings) body))]))
+|#
+
+(define (let*->nested-lets exp)
+ (let ([bindings (let*-bindings exp)]
+ [body (let*-body exp)])
+ (let*->let bindings body)))
+
+;; b
+#|
+
+It is enough to add an action for let* expression in eval, as eval
+gets recursively called for the transformed expressions (assuming that
+eval has case handlers for let expression whose action is to transform
+into lambda expression application and eval it).
+
+if we add the following action for let* expressions in eval:
+
+(eval (let*->nested-lets exp) env)
+ =>
+(eval (let-expression) env)
+=>
+(eval (let->combination exp) env)
+=>
+(eval (application exp parameters) env)
+
+
+|#
\ No newline at end of file
--- /dev/null
+#lang racket
+
+(provide let->combination)
+
+(define (tagged-list? exp tag)
+ (if (pair? exp)
+ (eq? (car exp) tag)
+ #f))
+
+(define (variable? expr)
+ (symbol? expr))
+
+(define (make-lambda params body)
+ (cons 'lambda (cons params body)))
+
+(define (let? expr)
+ (tagged-list? expr 'let))
+
+(define (named-let? expr)
+ (if (variable? (cadr expr))
+ #t
+ #f))
+
+(define (let-name expr)
+ (if (named-let? expr)
+ (cadr expr)
+ #f))
+
+(define (let-bindings expr)
+ (if (let-name expr)
+ (caddr expr)
+ (cadr expr)))
+
+(define (let-bindings-variables bindings) (map car bindings))
+(define (let-bindings-values bindings) (map cadr bindings))
+(define (let-body expr)
+ (if (let-name expr)
+ (cdddr expr)
+ (cddr expr)))
+
+(define (let->combination expr)
+ (let ([bindings (let-bindings expr)])
+ (let ([vars (let-bindings-variables bindings)]
+ [vals (let-bindings-values bindings)]
+ [body (let-body expr)])
+ (if (not (let-name expr))
+ (cons (make-lambda vars body) vals)
+ (list (list 'define (let-name expr) (make-lambda vars body))
+ (list (let-name expr) vals))))))
+
+(define ns (make-base-namespace))
+(eval (let->combination '(let ((x 2) (y 3)) (+ x y))) ns)
+(eval (let->combination '(let ((x 2) (y 3)) (+ x y))) ns)
+(let->combination '(let fib-iter ((a 1)
+ (b 0)
+ (count n))
+ (if (= count 0)
+ b
+ (fib-iter (+ a b) a (- count 1)))))
#lang racket
+(require "ex4_8.rkt" ;; for let and named let
+ "ex4_7.rkt")
+
;; metacircular evaluator
(define (eval exp env)
(cond ((self-evaluating? exp) exp)
env))
((begin? exp) (eval-sequence (begin-actions exp) env))
((cond? exp) (eval (cond->if exp) env))
+ ((let? exp) (eval (let->combination exp) env)) ;; from ex4.8
+ ((let*? exp) (eval (let*->nested-lets exp) env)) ;; from ex4_7
((application? exp)
(apply (eval (operator exp) env)
(list-of-values (operands exp) env)))