Abstract Data Type

Implementation of N-Dimensional Points

(define make-point list)

(define (point.dimension pt) (length pt))
(define (point.coord pt dim)
  (list-ref pt (- dim 1)))

(define (point.x pt) (point.coord pt 1))
(define (point.y pt) (point.coord pt 2))
(define (point.z pt) (point.coord pt 3))

Simple List Operations

(define (list? l)
  (or (null? l)
      (and (pair? l) (list? (cdr l)))))

(define (length l)
  (if (null? l)
      0
      (+ 1 (length (cdr l)))))

(define (list-ref l n)
  (cond ((null? l) (error "..."))
        ((= 0 n) (car l))
        (else (list-ref (cdr l) (- n 1)))))

Higher-Order List Operations

(define (map fn list-of-values)
  ;; MAP: (X->Y, X*) -> Y*
  (if (null? list-of-values)
      '()
      (cons (fn (car list-of-values))
            (map fn (cdr list-of-values)))))

(define (accumulate initial-value
                    operation list-of-elements)
  ;; ACCUMULATE: (X, (Y, X)->X, Y*) -> X
  (if (null? list-of-elements)
      initial-value
      (operation 
        (car list-of-elements)
        (accumulate initial-value operation
                    (cdr list-of-elements)))))

Filter

(define (inside-unit-sphere? point)
  (<= (point.to-origin point) 1))

(define (filter test list)
  ;; FILTER: (X->Boolean, X*) -> X*
  (cond ((null? list) '())
        ((test (car list))
         (cons (car list)
               (filter test (cdr list))))
        (else (filter test (cdr list)))))

(define (how-many-in-unit-sphere points)
  (accumulate 0 +
    (map (lambda (pt) 1)
         (filter inside-unit-sphere? 
                 points))))

Building Standard Lists into Scheme

(define (add . numbers)
  (add-up numbers))

(define (list . elements) elements)

(define list (lambda elements elements))

(define (add-up numbers)
  (apply + numbers))

(define (point.to-origin pt)
  (sqrt (apply + (map square pt))))

Trees: Leaf Nodes

(define leaf-tag "Leaf")

(define (make-leaf . coords)
  ;; MAKE-LEAF: (Sch-Num*) -> Leaf
  (cons leaf-tag coords))

(define (is-leaf? obj)
  (and (pair? obj)
       (eq? (car obj) leaf-tag)))

(define (leaf.point leaf) (cdr leaf))

Trees: Non-Leaf Nodes

(define node-tag "Node")

(define (make-node dist outside on-or-inside)
  ;; MAKE-NODE:
  ;;  (Sch-Num, (Node+Leaf), (Node+Leaf)) -> Node
  (list node-tag dist outside on-or-inside))

(define (is-node? obj)
  (and (pair? obj)
       (eq? (car obj) node-tag)))

(define (node.distance node)
  (list-ref node 1))

(define (node.outside node)
  (list-ref node 2))

(define (node.on-or-in node)
  (list-ref node 3))

Walking Down a Tree

(define (tree.farthest node-or-leaf)
  (if (is-node? node-or-leaf)
      (tree.farthest
        (node.outside node-or-leaf))
      (leaf.point node-or-leaf)))

A Generic Operation

(define (distance node-or-leaf)
  (if (is-node? node-or-leaf)
      (node.distance node-or-leaf)
      (point.to-origin
        (leaf.point node-or-leaf))))

Recursive Tree Walk

(define (tree.valid? node-or-leaf)
  (if (is-node? node-or-leaf)
      (let ((smaller
              (node.on-or-in node-or-leaf))
            (not-smaller
              (node.outside node-or-leaf))
            (my-distance
              (node.distance node-or-leaf)))
        (and (< (distance smaller) 
                my-distance)
             (>= (distance not-smaller)
                 my-distance)
             (tree.valid? smaller)
             (tree.valid? not-smaller)))
        #T))