sicp4.1.1-4.1.5節(jié)部分習(xí)題嘗試解答(update)
Posted on 2008-06-01 15:51 dennis 閱讀(1036) 評論(0) 編輯 收藏 所屬分類: 數(shù)據(jù)結(jié)構(gòu)與算法 、計(jì)算機(jī)科學(xué)與基礎(chǔ) 當(dāng)將用scheme寫的scheme求值器跑起來的時候,你不覺的興奮是不可能的,真的太酷了,太magic了。
習(xí)題4.2,如果將application?判斷放在define?判斷之前,那么求值(define x 3)將把define當(dāng)作一般的procedure應(yīng)用于參數(shù)x和3,可是define是特殊的語法形式,而非一般過程,導(dǎo)致出錯。
習(xí)題4.4,我的解答,eval增加兩個判斷:
如果用宏實(shí)現(xiàn)就簡單了:
習(xí)題4.5,cond的擴(kuò)展形式,也不難,在else子句之外增加個判斷,是否帶有=>符號,修改expand-clauses過程:
習(xí)題4.6,let如果用宏定義,類似這樣:
習(xí)題4.7,這里的關(guān)鍵在于let*->netsted-lets要遞歸調(diào)用,從let*的宏定義可以看出:
(let* ((x 1) (y (+ x 3))) (+ x y)) =》5
習(xí)題4.8,命名let,修改let->combination過程,判斷cadr是pair還是symbol,如果是前者,那就是一般的let,如果是symbol就是命名let語句,那么需要定義一個名為(cadr exp)的過程放在body里,注意,我們是在做語法轉(zhuǎn)換,因此,這個定義也應(yīng)該描述成符號,定義一個make-define過程來生成define語句:
習(xí)題4.1.4,原生的map過程接受的procedure,是以scheme內(nèi)在數(shù)據(jù)結(jié)構(gòu)表示的procedure,而在我們的求值器中,procedure的內(nèi)在數(shù)據(jù)結(jié)構(gòu)取決于我們,與原生的結(jié)構(gòu)不同,導(dǎo)致原生的map無法接受自制求值器的procedure,如果map也以求值器中的結(jié)構(gòu)定義,那么就沒有這個問題。因此,本質(zhì)上的困難就在于兩個求值器對procedure的數(shù)據(jù)結(jié)構(gòu)表示的不同。
習(xí)題4.1.5,著名的圖靈停機(jī)問題,先是假設(shè)存在halts?過程可以正確地判斷任何過程p和對象a是否p對a終止,定義了try過程:
(define (try p)
(if (halts? p p)
(run-forever)
'halted))
當(dāng)執(zhí)行(try try),如果這個過程可終止,那么(halts? try try)應(yīng)該返回false,也就是try過程對try不會終止,這與一開始的假設(shè)矛盾;如果這個過程將無窮運(yùn)行下去,那么(halts? try try)應(yīng)該返回true,也就是try對try終止,這也與(try try)將無窮運(yùn)行的假設(shè)矛盾。因此,可以推論出,我們不可能寫出一個過程halts?,使它能正確地判斷任何過程p和對象a是否p對a終止。
習(xí)題4.2,如果將application?判斷放在define?判斷之前,那么求值(define x 3)將把define當(dāng)作一般的procedure應(yīng)用于參數(shù)x和3,可是define是特殊的語法形式,而非一般過程,導(dǎo)致出錯。
習(xí)題4.4,我的解答,eval增加兩個判斷:
((and? exp)
(eval-and (and-exps exp) env))
((or? exp)
(eval-or (or-exps exp) env))
實(shí)現(xiàn)謂詞和各自的過程:(eval-and (and-exps exp) env))
((or? exp)
(eval-or (or-exps exp) env))
(define (and? exp)
(tagged-list? exp 'and))
(define (and-exps exp)
(cdr exp))
(define (eval-and exps env)
(cond ((null? exps)
'true)
(else
(let ((result (eval (car exps) env)))
(if (not result)
result
(eval-and (cdr exps) env))))))
(define (or? exp)
(tagged-list? exp 'or))
(define (or-exps exp) (cdr exp))
(define (eval-or exps env)
(cond ((null? exps)
'false)
(else
(let ((result (eval (car exps) env)))
(if result
result
(eval-or (cdr exps) env))))))
(tagged-list? exp 'and))
(define (and-exps exp)
(cdr exp))
(define (eval-and exps env)
(cond ((null? exps)
'true)
(else
(let ((result (eval (car exps) env)))
(if (not result)
result
(eval-and (cdr exps) env))))))
(define (or? exp)
(tagged-list? exp 'or))
(define (or-exps exp) (cdr exp))
(define (eval-or exps env)
(cond ((null? exps)
'false)
(else
(let ((result (eval (car exps) env)))
(if result
result
(eval-or (cdr exps) env))))))
如果用宏實(shí)現(xiàn)就簡單了:
(define-syntax and
(syntax-rules ()
((_) #t)
((_ e) e)
((_ e1 e2 e3
)
(if e1 (and e2 e3
) #f))))
(define-syntax or
(syntax-rules ()
((_) #f)
((_ e) e)
((_ e1 e2 e3
)
(let ((t e1))
(if t t (or e2 e3
))))))
(syntax-rules ()
((_) #t)
((_ e) e)
((_ e1 e2 e3

(if e1 (and e2 e3

(define-syntax or
(syntax-rules ()
((_) #f)
((_ e) e)
((_ e1 e2 e3

(let ((t e1))
(if t t (or e2 e3

習(xí)題4.5,cond的擴(kuò)展形式,也不難,在else子句之外增加個判斷,是否帶有=>符號,修改expand-clauses過程:
(define (cond-extended-clauses? clause)
(and (> (length clause) 2) (eq? (cadr clause) '=>)))
(define (extended-cond-test clause)
(car clause))
(define (extended-cond-recipient clause)
(caddr clause)
(define (expand-clauses clauses)
(if (null? clauses)
'false
(let ((first (car clauses))
(rest (cdr clauses)))
(cond ((cond-else-clauses? first)
(if (null? rest)
(sequence->exp (cond-actions first))
(error "else clause is not LAST" clauses)))
((cond-extended-clauses? first) ;判斷是否擴(kuò)展形式
(make-if
(extended-cond-test first)
(list
(extended-cond-recipient first)
(extended-cond-test first))
(expand-clauses rest)))
(else
(make-if (cond-predicate first)
(sequence->exp (cond-actions first))
(expand-clauses rest)))))))
(and (> (length clause) 2) (eq? (cadr clause) '=>)))
(define (extended-cond-test clause)
(car clause))
(define (extended-cond-recipient clause)
(caddr clause)
(define (expand-clauses clauses)
(if (null? clauses)
'false
(let ((first (car clauses))
(rest (cdr clauses)))
(cond ((cond-else-clauses? first)
(if (null? rest)
(sequence->exp (cond-actions first))
(error "else clause is not LAST" clauses)))
((cond-extended-clauses? first) ;判斷是否擴(kuò)展形式
(make-if
(extended-cond-test first)
(list
(extended-cond-recipient first)
(extended-cond-test first))
(expand-clauses rest)))
(else
(make-if (cond-predicate first)
(sequence->exp (cond-actions first))
(expand-clauses rest)))))))
習(xí)題4.6,let如果用宏定義,類似這樣:
(define-syntax let
(syntax-rules ()
((_ ((x v)
) e1 e2
)
((lambda (x
) e1 e2
) v
))))
求值器擴(kuò)展,實(shí)現(xiàn)let->combination過程:(syntax-rules ()
((_ ((x v)


((lambda (x



(define (let? exp)
(tagged-list? exp 'let))
(define (let->combination exp)
(let ((vars (map car (cadr exp)))
(vals (map cadr (cadr exp)))
(body (caddr exp)))
(cons (make-lambda vars (list body)) vals)))
我們做的僅僅是syntax transform,將let轉(zhuǎn)成對應(yīng)的lambda形式。(tagged-list? exp 'let))
(define (let->combination exp)
(let ((vars (map car (cadr exp)))
(vals (map cadr (cadr exp)))
(body (caddr exp)))
(cons (make-lambda vars (list body)) vals)))
習(xí)題4.7,這里的關(guān)鍵在于let*->netsted-lets要遞歸調(diào)用,從let*的宏定義可以看出:
(define-syntax let*
(syntax-rules()
((_ ((var1 val1)) e1
)
(let ((var1 val1)) e1
))
((_ ((var1 val1) (var2 val2)
) e1
)
(let ((var1 val1))
(let* ((var2 val2)
)
e1
)))))
那么,let*->nested-lets可以定義為:(syntax-rules()
((_ ((var1 val1)) e1

(let ((var1 val1)) e1

((_ ((var1 val1) (var2 val2)


(let ((var1 val1))
(let* ((var2 val2)

e1

(define (let*? exp)
(tagged-list? exp 'let*))
(define (let*->nested-lets exp)
(let ((pairs (cadr exp))
(body (caddr exp)))
(if (null? (cdr pairs))
(list 'let pairs body)
(list 'let (list (car pairs)) (let*->nested-lets (list 'let* (cdr pairs) body))))))
測試一下:(tagged-list? exp 'let*))
(define (let*->nested-lets exp)
(let ((pairs (cadr exp))
(body (caddr exp)))
(if (null? (cdr pairs))
(list 'let pairs body)
(list 'let (list (car pairs)) (let*->nested-lets (list 'let* (cdr pairs) body))))))
(let* ((x 1) (y (+ x 3))) (+ x y)) =》5
習(xí)題4.8,命名let,修改let->combination過程,判斷cadr是pair還是symbol,如果是前者,那就是一般的let,如果是symbol就是命名let語句,那么需要定義一個名為(cadr exp)的過程放在body里,注意,我們是在做語法轉(zhuǎn)換,因此,這個定義也應(yīng)該描述成符號,定義一個make-define過程來生成define語句:
(define (make-define var parameters body)
(list 'define (cons var parameters) body))
然后修改let->combination過程,如上所述:(list 'define (cons var parameters) body))
(define (let->combination exp)
(if (symbol? (cadr exp))
(let ((var (cadr exp))
(vars (map car (caddr exp)))
(vals (map cadr (caddr exp)))
(pairs (caddr exp))
(body (cadddr exp)))
(cons (make-lambda vars (list (make-define var vars body) body)) vals))
(let ((vars (map car (cadr exp)))
(vals (map cadr (cadr exp)))
(body (caddr exp)))
(cons (make-lambda vars (list body)) vals))))
(if (symbol? (cadr exp))
(let ((var (cadr exp))
(vars (map car (caddr exp)))
(vals (map cadr (caddr exp)))
(pairs (caddr exp))
(body (cadddr exp)))
(cons (make-lambda vars (list (make-define var vars body) body)) vals))
(let ((vars (map car (cadr exp)))
(vals (map cadr (cadr exp)))
(body (caddr exp)))
(cons (make-lambda vars (list body)) vals))))
習(xí)題4.1.4,原生的map過程接受的procedure,是以scheme內(nèi)在數(shù)據(jù)結(jié)構(gòu)表示的procedure,而在我們的求值器中,procedure的內(nèi)在數(shù)據(jù)結(jié)構(gòu)取決于我們,與原生的結(jié)構(gòu)不同,導(dǎo)致原生的map無法接受自制求值器的procedure,如果map也以求值器中的結(jié)構(gòu)定義,那么就沒有這個問題。因此,本質(zhì)上的困難就在于兩個求值器對procedure的數(shù)據(jù)結(jié)構(gòu)表示的不同。
習(xí)題4.1.5,著名的圖靈停機(jī)問題,先是假設(shè)存在halts?過程可以正確地判斷任何過程p和對象a是否p對a終止,定義了try過程:
(define (try p)
(if (halts? p p)
(run-forever)
'halted))
當(dāng)執(zhí)行(try try),如果這個過程可終止,那么(halts? try try)應(yīng)該返回false,也就是try過程對try不會終止,這與一開始的假設(shè)矛盾;如果這個過程將無窮運(yùn)行下去,那么(halts? try try)應(yīng)該返回true,也就是try對try終止,這也與(try try)將無窮運(yùn)行的假設(shè)矛盾。因此,可以推論出,我們不可能寫出一個過程halts?,使它能正確地判斷任何過程p和對象a是否p對a終止。