SICP读书笔记 2.5
SICP CONCLUSION
讓我們舉起杯,祝福那些將他們的思想鑲嵌在重重括號之間的Lisp程序員 !
祝我能夠突破層層代碼,找到住在里計算機的神靈!
目錄
1. 構造過程抽象
2. 構造數據抽象
3. 模塊化、對象和狀態
4. 元語言抽象
5. 寄存器機器里的計算
Chapter 2
- 構造數據對象
練習答案
帶有通用型操作系統
這里講會實現一個通用型的算術包,大概可以分為幾個抽象層
- add sub mul div四個操作,支持所有這個算術包里所有支持的數據
- 有理數算術 復數算術 常規算術
- 最底層的各自實現
使用前一節的數據導向
(define (add x y) (apply-generic 'add x y)) (define (sub x y) (apply-generic 'sub x y)) (define (mul x y) (apply-generic 'mul x y)) (define (div x y) (apply-generic 'div x y))(define (install-scheme-number-package)(define (tag x)(attach-tag 'scheme-number x))(put 'add '(scheme-number scheme-number)(lambda (x y) (tag (+ x y))))(put 'sub '(scheme-number scheme-number)(lambda (x y) (tag (- x y))))(put 'mul '(scheme-number scheme-number)(lambda (x y) (tag (* x y))))(put 'div '(scheme-number scheme-number)(lambda (x y) (tag (/ x y))))(put 'make 'scheme-number(lambda (x) (tag x)))'done)(define (make-scheme-number n)((get 'make 'scheme-number) n))(define (install-rational-package);; internal procedures(define (numer x) (car x))(define (denom x) (cdr x))(define (make-rat n d)(let ((g (gcd n d)))(cons (/ n g) (/ d g))))(define (add-rat x y)(make-rat (+ (* (numer x) (denom y))(* (numer y) (denom x)))(* (denom x) (denom y))))(define (sub-rat x y)(make-rat (- (* (numer x) (denom y))(* (numer y) (denom x)))(* (denom x) (denom y))))(define (mul-rat x y)(make-rat (* (numer x) (numer y))(* (denom x) (denom y))))(define (div-rat x y)(make-rat (* (numer x) (denom y))(* (denom x) (numer y))));; interface to rest of the system(define (tag x) (attach-tag 'rational x))(put 'add '(rational rational)(lambda (x y) (tag (add-rat x y))))(put 'sub '(rational rational)(lambda (x y) (tag (sub-rat x y))))(put 'mul '(rational rational)(lambda (x y) (tag (mul-rat x y))))(put 'div '(rational rational)(lambda (x y) (tag (div-rat x y))))(put 'make 'rational(lambda (n d) (tag (make-rat n d))))'done)(define (make-rational n d)((get 'make 'rational) n d))特殊的在復數算術包中,它構造了兩層標志的抽象系統,首先由complex標志引導到復數包,再由rectangular引導到兩種表示
(define (make-complex-from-real-imag x y)((get 'make-from-real-imag 'complex) x y))(define (make-complex-from-mag-ang r a)((get 'make-from-mag-ang 'complex) r a))不同類型的數據組合
到目前為止,我們都把算術操作看作是不同類型的單獨操作,現在我們要來實現的是跨類型操作
這一方法的局限非常明顯,太復雜,太麻煩
用一個特殊的強制表格存儲我們的強制類型變換操作
(define (scheme-number->complex n)(make-complex-from-real-imag (contents n) 0));: (put-coercion 'scheme-number 'complex scheme-number->complex)在驚醒操作分派的時候,需要先判斷是否需要強制類型轉換
(define (apply-generic op . args)(let ((type-tags (map type-tag args)))(let ((proc (get op type-tags)))(if proc(apply proc (map contents args))(if (= (length args) 2)(let ((type1 (car type-tags))(type2 (cadr type-tags))(a1 (car args))(a2 (cadr args)))(let ((t1->t2 (get-coercion type1 type2))(t2->t1 (get-coercion type2 type1)))(cond (t1->t2(apply-generic op (t1->t2 a1) a2))(t2->t1(apply-generic op a1 (t2->t1 a2)))(else(error "No method for these types"(list op type-tags))))))(error "No method for these types"(list op type-tags)))))))但是這個方法還是由它的局限,如果我們考慮在轉換失敗的時候,可以通過第三種類型來轉換成功。所以就要建立類型的層次結構
類型的層次結構
結構大至是所有的整數都可以看作有理數,有理數又可以看作是實數,實數又可以看作復數
在面對一個類型塔結構的時候,我們在增加新類型時就非常的方便,只要讓它作為是誰的超類或者子類,這時也不需要直接定義整數到復數的轉換,只需要在每個層次種增加一個轉換就可以了。而對于每個類型,都會有一個自己的raise方法。而這里體現的另一種思想就是繼承,每個類型都可以繼承它的超類所有的方法,也就是說,如果所需操作在給定類型里沒有定義,那么我們就開始向塔頂爬升。
但類型層次結構也有它的不足,每個類型可能是多個類型的子類型,也可能是多個類型的超類型
實例:符號代數
- 多項式算術
遞歸:在多項式計算中,多項式的系數也可能是一個多項式
數據抽象,先提供一套操作函數去進行操作,之后再實現:
(define (add-poly p1 p2)(if (same-variable? (variable p1) (variable p2))(make-poly (variable p1)(add-terms (term-list p1)(term-list p2)))(error "Polys not in same var -- ADD-POLY"(list p1 p2))))(define (mul-poly p1 p2)(if (same-variable? (variable p1) (variable p2))(make-poly (variable p1)(mul-terms (term-list p1)(term-list p2)))(error "Polys not in same var -- MUL-POLY"(list p1 p2))))考慮項表的操作(慣例操作,先提供一套操作函數):
- empty-termlist?
- adjoin-term
- order
- coeff
- make-term
這里使用add,提現了數據抽象和通用型操作的的威力,這里的多項式的系數可以是任何算術系統里所擁有的,如果將這個多項式計算安裝到系統中,系數也就同樣支持多項式看,產生一個深度遞歸
項表的表示
表示形式的選擇
稠密多項式:直接采用其系數作為表
稀疏多項式:次數和系數的對應作為表
一個多項式可能有由許多不一樣的對象組成的,但是這并不會給算術系統造成多大的麻煩,因為在算術系統中使用的數據導向方法會幫我們做出各種正確操作,只需要我們實現了各部分的操作,并且安裝到算術系統中
這一節里講的是通過層層的數據抽象來實現更通用型的系統,在解決底層數據不同表示上,給出了兩種方法,一種是類型標識,一種是數據導向。在這個系統中,抽象是層層遞進的關系,最頂部的通用操作到每一層的分派到具體操作中。在之后的跨類型操作,提出了繼承的概念
這一章里主要提出的是數據抽象的概念和構造數據抽象,并利用數據抽象去構造更通用型的操作。其中在Scheme里構造數據抽象依托的是CONS,而其中的關鍵思想應該是閉包性質,在基于數據抽象的概念上,提出了一個非常有用的概念,就是以數據抽象作為程序中的介質,提高程序的模塊性,降低程序的耦合性,把各個模塊的依賴性降低到對數據結構的操作,再之后就是引入了符號數據。然后通過層層的丑行構造更通用的算術系統,其中介紹了兩種非常有用的方法,類型標識、消息傳遞和數據導向。其中一樣是運用之前所講的分層思想,每一個層次都有自己的基本元素和組合方法抽象方法,最后就是再進行跨類型操作引入的類型塔中提到的繼承概念,旨在建立對象和對象之間的聯系
轉載于:https://www.cnblogs.com/secoding/p/10532575.html
總結
以上是生活随笔為你收集整理的SICP读书笔记 2.5的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 线性稳压器和开关稳压器比较
- 下一篇: SpringBoot+Vue项目实例开发