我一直在尝试理解 SICP 中的数据导向编程,但到目前为止还做不到。我对此有一些疑问。这是 SICP 的原始代码:
(define (make-table)
(let ((local-table (list '*table*)))
(define (lookup key-1 key-2)
(let ((subtable
(assoc key-1 (cdr local-table))))
(if subtable
(let ((record
(assoc key-2 (cdr subtable))))
(if record (cdr record) false))
false)))
(define (insert! key-1 key-2 value)
(let ((subtable
(assoc key-1 (cdr local-table))))
(if subtable
(let ((record
(assoc key-2 (cdr subtable))))
(if record
(set-cdr! record value)
(set-cdr! subtable(cons (cons key-2 value)
(cdr subtable)))))
(set-cdr! local-table(cons (list key-1 (cons key-2 value))
(cdr local-table)))))
'ok)
(define (dispatch m)
(cond ((eq? m 'lookup-proc) lookup)
((eq? m 'insert-proc!) insert!)(else (error "Unknown operation: TABLE" m))))
dispatch))
(define (assoc key records)
(cond ((null? records) false)
((equal? key (caar records)) (car records))
(else (assoc key (cdr records)))))
(define operation-table (make-table))
(define get (operation-table 'lookup-proc))
(define put (operation-table 'insert-proc!))
(define (make-from-real-imag-rectangular x y)
(attach-tag 'rectangular (cons x y)))
(define (make-from-mag-ang-polar r a)
(attach-tag 'polar (cons r a)))
(define (make-from-real-imag x y)
(make-from-real-imag-rectangular x y))
(define (make-from-mag-ang r a)
(make-from-mag-ang-polar r a))
(define attach-tag cons)
(define type-tag car)
(define contents cdr)
(define (install-rectangular-package)
;;internal procedures
(define (real-part z)(car z))
(define (imag-part z)(cdr z))
(define (make-from-real-imag)(cons x y))
(define (magnitude z)
(sqrt (+ (square (real-part z))
(square (imag-part z)))))
(define (angle z)
(atan (imag-part z)(real-part z)))
(define (make-from-mag-ang r a)
(cons (* r (cos a))(* r (sin a))))
;;interface to the rest of the system
(define (tag x)(attach-tag 'rectangular x))
(put 'real-part '(rectangular) real-part)
(put 'imag-part '(rectangular) imag-part)
(put 'magnitude '(rectangular) magnitude)
(put 'angle '(rectangular) angle)
(put 'make-from-real-imag 'rectangular
(lambda (x y) (tag (make-from-real-imag x y))))
(put 'make-from-mag-ang 'rectangular
(lambda (r a) (tag (make-from-mag-ang r a ))))
'done)
(define (install-polar-package)
;; internal procedures
(define (magnitude z) (car z))
(define (angle z) (cdr z))
(define (make-from-mag-ang r a) (cons r a))
(define (real-part z) (* (magnitude z) (cos (angle z))))
(define (imag-part z) (* (magnitude z) (sin (angle z))))
(define (make-from-real-imag x y)
(cons (sqrt (+ (square x) (square y)))
(atan y x)))
;; interface to the rest of the system
(define (tag x) (attach-tag 'polar x))
(put 'real-part '(polar) real-part)
(put 'imag-part '(polar) imag-part)
(put 'magnitude '(polar) magnitude)
(put 'angle '(polar) angle)
(put 'make-from-real-imag 'polar
(lambda (x y) (tag (make-from-real-imag x y))))
(put 'make-from-mag-ang 'polar
(lambda (r a) (tag (make-from-mag-ang r a))))
'done)
(install-polar-package)
(install-rectangular-package)
首先,我不知道如何使用 make-from-real-imag 或 make-from-mag-ang 将条目放入表中
(put 'make-from-real-imag 'rectangular
(lambda (x y) (tag (make-from-real-imag x y))))
您能告诉我如何准确地调用此过程来放置条目吗?
当我调用 get 而不输入任何像这样的条目时:
(get 'real-part '(rectangular))
它返回(lambda (z) (car z))
为什么?如果表中没有条目或者我的代码有问题,它应该返回 false ?
在包内部有“系统其余部分的接口(interface)”部分,如何在没有任何参数的情况下放置过程调用选择器(实数部分、图像部分、幅度、角度)?
(put 'real-part '(polar) real-part)
最佳答案
在看过 Brian Harvey 的 cs61a 第 16 课(关于泛型运算符)后,我对数据定向编程有了一些了解。这是 Brian Harvey 的 cs61a 第 16 课的 YouTube 链接 https://www.youtube.com/watch?v=zgbBNEuHs2w
当我们调用包时,过程会作为 lambda 函数放入表中。这就是为什么当我们调用 (get 'real-part '(矩形))
时,它会返回 (lambda (z) (car z))
因此 put
过程是用包来调用的,例如(put 'real-part '(极地)实数部分)
并且这个过程需要 (define (实部 z) (* (magnitude z) (cos (angle z))))
作为参数并作为表的条目
这些过程是本书中上述过程的延续。
(define (map proc items)
(if (null? items)
nil
(cons (proc (car items))
(map proc (cdr items)))))
(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))
(error
"No method for these types: APPLY-GENERIC"
(list op type-tags))))))
(define (real-part z) (apply-generic 'real-part z))
(define (imag-part z) (apply-generic 'imag-part z))
(define (magnitude z) (apply-generic 'magnitude z))
(define (angle z) (apply-generic 'angle z))
(define (make-from-real-imag x y)
((get 'make-from-real-imag 'rectangular) x y))
(define (make-from-mag-ang r a)
((get 'make-from-mag-ang 'polar) r a))
例如,要创建一个用于矩形表示的复数,我调用:
(define c-num1 (make-from-real-imag 5 3))
现在我们有一个 c-num1
对象作为 (长方形 5 . 3)
我们可以使用apply-generic
调用该对象上的任何操作
例如 (apply-generic 'real-part c-num1)
我们得到 5 或 (apply-generic 'imag-part c-num1)
我们得到 3或者我们直接调用使用 apply-generic
定义的 (real-part c-num1)
。
关于scheme - 数据导向编程 SICP,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72590616/