计算机程序的构造和解释 练习题2.76

带有显式分派的通用性操作

在加入一个新类型时,需要添加新类型的构造过程、选择过程、各自通用操作过程,另外还需要在通用操作过程中加入数据标识的判断,根据数据标识执行相应的数据类型过程。
而如果需要添加新操作,则需要在每一种类型里面添加各自的新的操作,还需要添加新操作的通用过程。
拿书中复数的实现举例添加新类型需要修改的编码。

#lang racket
//加入新类型的构造过程和选择过程
(define (real-part-polar z)
  (* (magnitude-polar z) (cos (angle-polar z))))
(define (imag0part-polar z)
  (* (magnitude-polar z) (sin (angle-polar z))))

(define (magintude-polar z) (car z))
(define (angle-polar z) (cdr z))
(define (make-from-real-imag-polar x y)
  (attach-tag 'polar 
              (cons (sqrt (+ (square x) (square y)))
                    (atan y x))))
(define (make-from-mag-ang-polar r a)
  (attach-tag 'polar (cons r a)))
//加入标识判断
(define (reak-part z)
  (cond ((rectangular? z)
         (real-part-rectangular (contents z)))
        ((polar? z)
         (real-part-polar (contents z)))
        (else (error "Unknown type -- REAL-PART" z))))

不论添加新类型还是新操作都需要修改大量代码来实现。

数据向导风格

在加入一个新类型时,需要添加新类型的过程包就可以,其他地方不需要变动。

#lang racket

(define (install-polar-package)
  (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)))
  (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)

如果添加新操作,也可以添加一个安装包,这个安装包里面包含每一种类型对应新操作的过程,比如下面这种方式。

(define (install-newop-package)
  (define (newop-rectangular z)
    (car z))
  (define (newop-polar z)
    (car  z))
  (put 'newop '(rectangular) newop-rectangular)
  (put 'newop '(polar) newop-polar))

(define (newop z) (apply-generic 'newop z))

这种方式有操作信息表,比较灵活,不管是添加新类型或者新操作,只要操作“操作信息表”就可以。

消息传递的风格

在加入一个新类型时,需要添加新类型的构造程序就可以,其他地方不需要变动。

(define (make-from-mag-ang r a)
   (define (dispatch op)
    (cond ((eq? op 'real-part) (* r (cos a)))
          ((eq? op 'imag-part) (* r (sin a)))
          ((eq? op 'magnitude) r)
          ((eq? op 'angle) a)
          (else
           (error "Unknown op -- MAKE-FROM-MAG-ANG" op))))
  dispatch)

如果添加新操作,则需要每一个构造过程加入新的操作函数。

(define (make-from-mag-ang r a)
   (define (dispatch op)
    (cond ((eq? op 'real-part) (* r (cos a)))
          ((eq? op 'imag-part) (* r (sin a)))
          ((eq? op 'magnitude) r)
          ((eq? op 'angle) a)
          ((eq? op 'newop) (square r))
          (else
           (error "Unknown op -- MAKE-FROM-MAG-ANG" op))))
  dispatch)

消息传递的风格,不需要过多的选择函数,代码量比较小,但是添加新操作比较麻烦,每种都需要添加。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值