[PRL] Accumulator for container capacity

William D Clinger will at ccs.neu.edu
Fri Sep 23 13:05:39 EDT 2005


Here is a version of the code that uses the purely functional
Visitor pattern.  If you don't like the use of foldr inside
the check procedure, you can define make-Container-FoldR in
the obvious way and make the obvious changes to check.

Will

--------

;(module container mzscheme

  (define-struct Container (contents capacity))
  (define-struct Simple (name weight))

  ;; --- MF added ---
  ;; A Container is (make-Container (Listof Item) Number).
  ;;
  ;; An Item is one of:
  ;;  -- (make-Simple Symbol Number)
  ;;  -- Container
  ;; --- end added ---

  ;; --- WDC added ---
  ;; 
  ;; A Container-Visitor: Container -> T is
  ;;     (make-Container-Visitor simple-visitor container-visitor)
  ;; where
  ;; simple-visitor: Symbol x Number -> T
  ;; container-visitor: (Listof T) x Number -> T

  (define (make-Container-Visitor simple-visitor container-visitor)
    (define (visitor c)
      (cond ((Simple? c)
             (simple-visitor (Simple-name c) (Simple-weight c)))
            ((Container? c)
             (container-visitor (map visitor (Container-contents c))
                                (Container-capacity c)))
            (else ???)))
    visitor)

  ;; --- end added ---

  ;; Test object c1 in Scheme

  ;; --- MF changed ---
  (define c-1
    (make-Container (list (make-Simple "apple" 1))
      1))

  (define c0
    (make-Container (list (make-Simple "pencil" 1)
                      c-1
                      (make-Simple "orange" 1))
      1))

  (define c1
    (make-Container (list (make-Simple "apple" 1)
                      c0
                      (make-Simple "orange" 1)
                      (make-Simple "kiwi" 1))
      5))
  ;; --- end changed ---

  ;; -- mw changed --

  (define-struct wv (weight violations))
 
  (define (foldr f seed l)
    (if (null? l) seed
      (f (car l) (foldr f seed (cdr l)))))
          

  ;; check returns the total number of capacity violations in a container
  ;; check: Container -> int

  ;; --- WDC changed ---

  (define (check ac)
    (wv-violations
     ((make-Container-Visitor
       (lambda (name weight) (make-wv weight 0))
       (lambda (wvs capacity)
         (let* ((totals
                 (foldr (lambda (wv1 wv2)
                          (make-wv
                           (+ (wv-weight wv1) (wv-weight wv2))
                           (+ (wv-violations wv1) (wv-violations wv2))))
                        (make-wv 0 0)
                        wvs))
                (total-weight (wv-weight totals))
                (total-violations (wv-violations totals)))
           (make-wv total-weight
                    (if (> total-weight capacity)
                        (+ 1 total-violations)
                        total-violations)))))
      ac)))

  ;; --- end changed ---

;  )



More information about the PRL mailing list