[The Einstein Model of File Systems]
(define-struct dir (name size subs))
____________________________________________________________________
| |
v |
A directory is (make-dir symbol number list-of-directories) |
__________________________________________________ |
| | |
v | |
A list-of-directories is either | |
- empty | |
- (cons d lod) | |
where d is a directory and lod is a list-of-directories. | |
| | | |
| ---------------- |
---------------------------------------------------------
;; du : directory -> number ;; du computes the total disk usage of the directory by adding up all ;; directory sizes in a-dir (define (size a-dir) ...)
Since there are two data definitions, we need TWO templates:
Annotate them with mutual and self-references. These refs have the same structure as those in the data definitions.
Fill in the blanks.
Develop a program that also adds up file sizes
now add list-of-files to directory as a separate field; new mutual references; extend du a final time. This is pretty close to the real Unix du now!
;; path : dir symbol -> (listof name) ;; compute the list of directory names that leads to the first occurrence ;; of file-name in a directory contents -- empty if it doesn't exist (define (path a-dir file-name) ...)
(define MS (make-directory 'win3.1 empty empty)) (define Nxt (make-directory 'win empty 'world) (define Sys (make-directory 'sys (list Nxt MS) 'world)) (path MS 'world) = empty (path Nxt 'world) = (list 'win) (path Sys 'world) = (list 'sys 'win)
;; in-dir : directory symbol -> bool
;; determines whether directory with a-name occurs in a-dir
(define (in-dir? a-dir name)
(cond
[(eq? (dir-name a-dir) name) #t]
[(in-subs? (dir-subs a-dir) name) #t]
[else #f]))
;; in-dir : list-of-directories symbol -> bool
;; determines whether directory with a-name occurs in the list of directories
(define (in-subs lod name)
(cond
[(empty? lod) #f]
[else (or (in-dir? (first lod) name)
(in-subs? (rest lod) name))]))
Now compare the self-references in these two functions with those of the
data definitions.
(define (path-in-dir a-dir name)
(cond
[(in-files (dir-files a-dir) name) (list (dir-name a-dir))]
[(in-subs (dir-subs a-dir) name)
(cons (dir-name a-dir) (path-in-subs (dir-subs a-dir) name))]
[else empty]))
(define (path-in-subs lod name)
(cond
[(empty? lod) '???]
[else
(cond
[(in-dir (first lod) name)
(path-in-dir name)]
[else
(path-in-subs (rest lod) name)])]))
;; f : (listof symbols) (listof numbers) -> ??? ;; f combines symbols and numbers into records and ... (define (f aloS aloN) ...)
use two-dimensional analysis to figure out the conditionals---Cartesian product of choices!
| (empty? aloN) | (cons? aloN) | |
| (empty? aloS) | ||
| (cons? aloS) |
;; f : (listof symbols) (listof numbers) -> ???
______________________________________
_____________________________ |
| | | |
v v | |
(define (f aloS aloN) | |
(cond | |
((and (empty? aloS) (empty? aloN)) ...) | |
((and (cons? aloS) (empty? aloN)) | |
... (first aloS) ... | |
... (rest aloS) ...) -------------------------|
((and (empty? aloS) (cons? aloN)) | |
... (first aloN) ... | |
... (rest aloN) ...) ----------------------| |
(else | |
... (rest aloN) ... ---------------------- |
... (rest aloS) ... -------------------------
... (first aloN) ...
... (first aloS) ...
)))
There are many different recursions possible now:
(f aloS (rest aloN)) (f (rest aloS) aloN) (f (rest aloS) (rest aloN))Some functions need one of them; some functions need all three of them.
Here are two recommended little exercises that bring out the idea:
#|
zip : (listof symbols) (listof numbers) -> (listof (list names numbers))
(define (zip names phones) ...)
Purpose: combines corresponding items on the two lists, names and
phones, into `pairs' i.e. lists of two items
Example: (zip (list 'a 'b 'c) (list 0 1 2))
= (list (list 'a 0)
(list 'b 1)
(list 'c 2))
When the list are of different length, zip calls error with the first
item on the list that has left-over elements.
|#
Define the function merge, which consumes two sorted lists of numbers and produces a single sorted list of numbers w/o duplicates.
#|
merge : (listof number) (listof number) -> (listof number)
(define (merge l1 l2) ...)
Assumption: both l1 and l2 are sorted in ascending order
and are duplicate free
Purpose: produce a single list of all numbers in l1 and l2
in ascending order; if l1 and l2 each contain the same number
only include one in the result
Example: (merge (list 0 3 4 5) (list 1 2 3 9))
= (list 0 1 2 3 4 5 9)
|#
| Matthias Felleisen | This page was generated on Fri Apr 9 09:17:38 CDT 1999. |