;;; Example of "find", using map and foldr. ;;; It accesses the disk, using the function directory-list. ;;; (So the data definition doesn't really hold, since ;;; to the file system, all files are just strings (their name).) ;;; ;;; It is similar to accumulator approach, because a file's name ;;; is really a string which is the *full pathname*. (define directory? directory-exists?) (define file? file-exists?) ;; find: directory-name, filename --> list-of-directory-name ;; This version includes any directories that have the indicated name. ;; NOTE: the initial directory name should not be a relative ;; names like ".", since we'll fail to match the directory ;; with the target filename. ;; Use "normalize-path" if you want to fix this. ;; (define (find start target) (cond [(directory? start) (local [(define (prepend-curr-dir f) (build-path start f)) (define updated-names (map prepend-curr-dir (directory-list start))) (define sub-files (find-in-list updated-names target))] (if (string=? (base start) target) (cons start sub-files) sub-files))] [(file? start) (if (string=? (base start) target) (list start) empty)] [else (error 'find (format "file not found: ~s." start))])) ;; base: pathname --> string ;; Return the base element of the path name (eg w/o leading directories). ;; ;; This helper function is needed because find needs to compare ;; a filename with the entire pathname. ;; (define (base fpath) (let-values {[(root base must-be-dir?) (split-path (normalize-path fpath))]} base)) ;; find-in-list: list-of-pathnames, string --> list-of-pathnames. ;; Return a list of pathnames (all occurrences of target ;; within any of the input paths.) ;; (define (find-in-list lodf target) (foldr (lambda (fname others) (append (find fname target) others)) empty lodf)) (find "/home/comp210/Web/01fall/Lectures/" "the-nixon-tapes.mp3") (find "/home/comp210/Web/01fall/Lectures/" "lect13.xml") (find "/home/comp210/Web/01fall/" "lect13.xml") (find "/home/comp210/Web/01fall/" "index.html") ;(find "." "index.html") ;(find ".." "index.html") (find "/not/really/extant" "index.html")