SICP 問題 4.22
letを使えるようにする.
(define (analyze exp) (cond ((self-evaluating? exp) (analyze-self-evaluating exp)) ((quoted? exp) (analyze-quoted exp)) ((variable? exp) (analyze-variable exp)) ((assignment? exp) (analyze-assignment exp)) ((definition? exp) (analyze-definition exp)) ((if? exp) (analyze-if exp)) ((lambda? exp) (analyze-lambda exp)) ((let? exp) (analyze (let->combination exp))) ((begin? exp) (analyze-sequence (begin-actions exp))) ((cond? exp) (analyze (cond->if exp))) ((application? exp) (analyze-application exp)) (else (error "Unknown expression type: ANALYZE" exp)))) (define (let? exp) (tagged-list? exp 'let)) (define (let-parameters exp) (cadr exp)) (define (let-variables exp) (map car (let-parameters exp))) (define (let-expressions exp) (map cadr (let-parameters exp))) (define (let-bodys exp) (cddr exp)) (define (let->combination exp) (if (symbol? (cadr exp)) ;; 2番目の要素がシンボルならnamed-let (named-let->define (named-let-func-name exp) (named-let-variables exp) (named-let-expressions exp) (named-let-bodys exp)) (cons (make-lambda (let-variables exp) (let-bodys exp)) (let-expressions exp)))) ;; make-procedureのbodyのところについていたscan-out-definesのせいでエラー. ;; make-proceduren渡される時点でbodyはanalyzeした後のclosureになっているので ;; analyze-lambdaの中で内部定義をletに吐き出す. (define (make-procedure parameters body env) (list 'procedure parameters body env)) (define (analyze-lambda exp) (let ((vars (lambda-parameters exp)) (bproc (analyze-sequence (scan-out-defines (lambda-body exp))))) (lambda (env) (make-procedure vars bproc env))))