[TOC] ## 数据混合与区分 ### 计算 * 在图7.1所示的五个点中,有三个点位于x轴上,分别是C、D、E,因此只有两个点,A和B,需要使用坐标表示。使用新的点表示法可以更简洁地描述这些点:`(make-posn 6 6)`代表A;`( make-posn1 2)`代表B;而1、2、3分别代表C、D、E。 * 现在,如果要定义函数 distance-to-0,函数读入一个点,结果是该点到原点的距离. ![320F0C63-37D8-45F8-AB0E-47C9669074C4.png](http://yanxuan.nosdn.127.net/63520ef658c7ad7d532115aa6ff023b3.png) code ``` ; 计算点到原点的距离 ; number -> number ; or struct-posn ->number (define (distance-to-0 a-pixel) (cond [(number? a-pixel) a-pixel ] [(posn? a-pixel ) (hypotenuse (posn-x a-pixel) (posn-y a-pixel) )] )) ; 计算斜边 ; number,number ->number ; (3,4) -> 5 (define (hypotenuse x y) (sqrt (+ (* x x) (* y y)))) ; 输出 5 (distance-to-0 (make-posn 3 4)) ``` ### 设计处理混合数据的函数 数据分析和设计 * 分析问题表述的任务之一就是判断该问题有没有涉及不同类型的数据,这类数据通常称为**混合数据(Mixed Data)**,或称为**数据的联合体(Union)**。 * 换句话说,数据分析必须考虑多个因素。 * 第一,必须确定问题提及多少种不同的数据类型,各自的属性又是什么。如果存在多个不同的数据类型,就将它们组成混合数据; * 第二,必须理解涉及的对象有没有多个属性,如果某个对象有多个属性,就用结构体来表示它。因此,数据定义可能包含多个子句,列举了多种可能的情况。事实上,数据分析可能会生成一个多层的数据定义。 模板 * 模板就是把输入数据翻译成 Scheme表达式。 * 例如,有一个数据定义,列举了多个不同的事物。 * 第一步是写下一个cond表达式,其子句数量与数据定义所包含的不同类型的数据种类的数目一样; * 第二步是给每一个子句加上条件,与数据定义中相应的子类型相对应,当输入属于该子类型时,条件成立。 * 模板的例子 ``` // 不写距离逻辑 ;; f :shape -> ??? (define (f-shape) (cond [(square? a-shape) ...] [(circle? a-shape) ...])) ``` 主体 * 模板将任务分割成多个子任务。现在可以单独处理每一个cond子句了。事实上,只需简单地考虑如果输入是某种类型的数据,输岀应该是什么就可以了。因而在处理某个特定的子句时,可以忽略其他情况。 #### 一个完整的例子 ``` ;数据定义: (define-struct circle (center radius)) (define-struct square (nw length) ;; shape是下列二者之 ;; 1.结构体:(make- circle p s) ;; 其中 p 是 posn 结构体,s是数;或 ;; 2.结构体:(make- square p s) ;; 其中 p 是 posn 结构体,s 是数 ;; 例子: 参见测试 ;; 模板: ;;(define (f a-shape) ;; (cond ;; [(square? a-shape) ...] ;; [(circle? a-shape) ...])) ;; 定义 (define (perimeter a-shape) (cond [(circle? a-shape) (* (* 2 (circle-radius a-shape)) pi)] [(square? a-shape) (* (square-length a-shape) 4)])) ;; 测试:(即例子) (= (perimter (make-square ... 3)) 12) (= (perimter (make-square ... 1)) (* 2 pi)) ```