scheme - 数据导向编程 SICP

标签 scheme sicp

我一直在尝试理解 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/

相关文章:

python - 类实例实现,初始化实例——来自SICP python

macos - 如何让方案解释器在 Emacs 中工作?

scheme - 映射!如果列表为空,无法将元素追加到列表中?

scheme - 如何在 guile 中创建 cairo 曲面

algorithm - Tic Tac Toe MiniMax 方案

haskell - 如何深入理解SICP中描述的信号流图?

emacs - 在 GNU Emacs 中执行 LISP 程序

lambda - 跟踪 lambda 表达式求值

Scheme Sum from a to b 迭代