zoukankan      html  css  js  c++  java
  • ch2

    (不太会用mit scheme,在racket下#lang planet neil/sicp也可以搭建相应的开发环境。

    2.30-2.31(P75 P76)延伸出treemap,WIKI上treemap是一种数据可视化的方式。

    而在书中,直接定义:

    (define (tree-map f tree)
        (cond ((null? tree)                         ; 空树
                '())
              ((not (pair? tree))                   ; 叶子节点
                (f tree))
              (else
                (cons (tree-map f (car tree))       ; 递归处理左右子树
                      (tree-map f (cdr tree))))))

    null?在pair?之前是因为null也会被认为是not pair?。

    使用map定义:

    (define (tree-map f tree)
        (map (lambda (sub-tree)
                 (if (pair? sub-tree)
                     (tree-map f sub-tree)  ; 处理子树
                     (f sub-tree)))         ; 处理节点
             tree))

    lisp中map使用深度优先原则对表的元素进行操作,如果有多个表则从每个表的第一个元素开始操作。

    P77至P79引出程序的模块化(来自于信号处理)

    无论是 计算奇数叶子的平方合

    #lang planet neil/sicp
    (define (sum-odd-squares tree)
      (cond ((null? tree) 0)
            ((not (pair? tree))
             (if (odd? tree) (square tree) 0))
            (else (+ (sum-odd-squares (car tree))
                     (sum-odd-squares (cdr tree))))))

    还是构造偶数斐波那契数的表

    #lang planet neil/sicp
    (define (even-fibs n)
      (define (next k)
        (if (> k n)
            nil
            (let ((f (fib k)))
              (if (even? f)
                  (cons f (next (+ k 1)))
                  (next (+ k 1))))))
      (next 0))

    都经过了 枚举、过滤、映射、累积 这四个步骤

    所以可以进一步抽象

    过滤
    (define (filter predicate sequence)
      (cond ((null? sequence) nil)
            ((predicate (car sequence))
             (cons (car sequence)
                   (filter predicate (cdr sequence))))
             (else (filter predicate (cdr sequence)))))
    
    
    累积
    (define (accumulate op initial sequence)
      (if (null? sequence)
          initial
          (op (car sequence)
              (accumulate op initial (cdr sequence)))))
    
    映射只要使用map就可以
    
    枚举需要根据情况编写
    
    这样,原来的sum-odd-squares 和 even-fibs就可以写成
    (define (sum-odd-squares tree)
      (accumulate +
                  0
                  (map square
                       (filter odd?
                               (enumerate-tree tree)))))
    
    (define (even-fib n)
      (accumulate cons
                  nil
                  (filter even?
                       (map fib
                               (enumerate-interval 0 n)))))

    P100开始构造求导函数deriv

    P117开始希望用一个复数的例子说明数据导向的程序开发

    #lang planet neil/sicp
    (define (add-complex z1 z2)
      (make-from-real-img (+ (real-part z1) (real-part z2))
                          (+ (imag-part z1) (imag-part z2))))
    (define (sub-complex z1 z2)
      (make-from-real-img (- (real-part z1) (real-part z2))
                          (- (imag-part z1) (imag-part z2))))
    (define (mul-complex z1 z2)
      (make-from-mag-ang (* (magnitude z1) (magnitude z2))
                         (+ (angle z1) (angle z2))))
    (defien (div-complex z1 z2)
      (make-from-mag-ang (/ (magnitude z1) (magnitude z2))
                         (- (angle z1) (angle z2))))
    
    
    ;Ben
    (define (real-part z) (car z))
    (define (imag-part z) (cdr z))
    (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-real-imag x y)
      (cons x y))
    (define (make-from-mag-ang r a)
      (cons (* r (cos a))(* r (sin a))))
    
    ;Alyssa
    ;(define (real-part z)
    ;  (* (magnitude z) (cos (angle z))))
    ;(define (imag-part z)
    ;  (* (magnitude z) (sin (angle z))))
    ;(define (magnitude z)
    ;  (car z))
    ;(define (angle z)
    ;  (cdr z))
    ;(define (make-from-real-imag x y)
    ;  (cons (sqrt (+ (square x) (square y)))
    ;        (atan y x)))
    ;(define (make-from-mag-ang r a) (cons r a))
    
    
    ;helper function
    (define (attach-tag type-tag contents)
      (cons type-tag contents))
    (define (type-tag datum)
      (if (pair? datum)
        (car datum)
        (error "Bad tagged datum -- TYPE-TAG " datum)))
    (define (contents datum)
      (if (pair? datum)
          (cdr datum)
          (error "Bad tagged datum -- CONTENTS" datum)))
    (define (rectangular? z)
      (eq? (type-tag z) 'rectangular))
    (define (polar? z)
      (eq? (type-tag z) 'polar))
    
    
    
    ;combind Ben and Alyssa(select)
    (define (real-part z)
      (cond ((rectangular? z)
             (real-part-rectangylar (contentes z)))
            ((polar? z)
             (real-part-polar (contents z)))
            (else (error "Unknown type -- REAL-PART" z))))
    (define (imag-part z)
      (cond ((rectangular? z)
             (imag-part-rectangular (contents z)))
            ((polar? z)
             (real-part-polar (contents z)))
            (else (error "Unknown type -- IMAG-PART" z))))
    (define (magnitude z)
      (cond ((rectangular? z)
             (magnitude-rectangular (contents z)))
            ((polar? z)
             (magnitude-polar (contents z)))
            (else (error "Unknow type -- MAGNITUDE" z))))
    (define (angle z)
      (cond ((rectangular? z)
             (angle-rectangular (contents z)))
            ((polar? z)
             (angle-polar (contents z)))
            (else (error "Unknow type -- ANGLE" z))))

    但是这样写的缺点也很明显,就是对于不同表示的复数对象,选择函数会在名称上有所重复,而且当这样的对象不再是两个而是上百个的时候,

    修改程序会变得极为麻烦,我们引入 get 和put函数来优化这一过程。(put <op><type><item>)

    (get<op><type>)

    其中的参数op 和type都作为索引来操作item,而put和get就是在一个表单里面放进和拿出相应的函数,这样一组复数的过程就可以类似“安装包”一样安装到表单内。

    (define (install-rectangular-package)
        ;; internal procedures
    (define (real-part z) (car z))
    (define (imag-part z) (cdr z))
    (define (make-from-real-imag x y)
         (cons x y))
    (define(magnitudez)
        (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)
    install-rectangular-package

    install-polar-package与之类似,不再赘述。

    其特点是 1:用一个无参过程包装 2:所有命名都是内部的,相同命名不会冲突

    复数运算过程的实现基础是一个通用的选择过程,它通过操作名和类型标签在表单中寻找操作。

    (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))

    Message passing。第三章详述

    P128一个包含通用型操作的系统

    考虑将之前讲的有理数算数操作、复数算数操作和系统自带的常规算数操作合为一体,使用数据导向完成这一设计。

    实现之后只需要:

    (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 (attach-tag type-tag x)
      (cons (type-tag x)))
    (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))

    创建带标志的常规数了。
  • 相关阅读:
    python 之os模块用法大全
    web自动化测试常用的定位方式有哪些?
    Jenkins
    吴恩达机器学习笔记:如何debug一个学习算法?
    贝叶斯网络
    leetcode-32. Longest Valid Parentheses
    leetcode4 median Of two sorted array
    leetcode21
    vs2017问题集锦
    LIS
  • 原文地址:https://www.cnblogs.com/autoria/p/4806237.html
Copyright © 2011-2022 走看看