我正在尝试编写一个使用目录树和文件名的函数查找,并确定目录树中是否存在具有该名称的文件。我在树的第一层(读!)中使用文件编写的内容,但是并没有进一步“看到”文件。知道文件是否不在树中的唯一方法是是否每个目录和文件已选中,但某些目录没有文件,而其他目录没有目录,但有些目录没有。对于我知道的树中的文件,我所做的一切都返回false。我不知道该怎么写假条件。
(define-struct dir (name dirs files))
(define-struct file (name size content))
(define fs (make-dir 'TS
(list (make-dir 'Text empty
(list
(make-file 'part1 99 empty)
(make-file 'part2 52 empty)
(make-file 'part3 17 empty)))
(make-dir 'Libs
(list
(make-dir 'Code empty
(list
(make-file 'hang 8 empty)
(make-file 'draw 2 empty)))
(make-dir 'Docs empty
(list
(make-file 'read! 19 empty)))) (list)))
(list (make-file 'read! 10 empty))))
(define (find fs name)
(cond
[(not (empty? (dir-dirs fs)))
(dp (dir-dirs fs) name)]
[(not (empty? (dir-files fs)))
(fc (dir-files fs) name)]
[else false]))
(define (dp dirs name) ;consumes lists of directories
(cond
[(empty? dirs) false] ;I don't know what else to put here but false
[else (find (first dirs) name)
(dp (rest dirs) name)]))
(define (fc files name) ;consumes lists of files
(cond
[(empty? files) false]
[(symbol=? name (file-name (first files))) true]
[else (fc (rest files) name)]))
(define-struct file [name size content])
; A File is a structure:
; (make-file Symbol N List)
(define-struct dir [name dirs files])
; A Dir is a structure:
; (make-dir Symbol Dir* File*)
; A Dir* is one of:
; – '()
; – (cons Dir Dir*)
; A File* is one of:
; – '()
; – (cons File File*)
; TS
; ├── Libs
; │ ├── Code
; │ │ ├── draw
; │ │ └── hang
; │ └── Docs
; │ └── read!
; ├── Text
; │ ├── part1
; │ ├── part2
; │ └── part3
; └── read!
; files
(define hang (make-file 'hang 8 empty))
(define draw (make-file 'draw 2 empty))
(define read!-in-docs (make-file 'read! 19 empty))
(define read!-in-ts (make-file 'read! 10 empty))
(define part1 (make-file 'part1 99 empty))
(define part2 (make-file 'part2 52 empty))
(define part3 (make-file 'part3 17 empty))
; directories
(define code (make-dir 'Code '() (list hang draw)))
(define docs (make-dir 'Docs '() (list read!-in-docs)))
(define text (make-dir 'Text '() (list part1 part2 part3)))
(define libs (make-dir 'Libs (list code docs) '()))
(define ts (make-dir 'TS (list text libs) (list read!-in-ts)))
; Dir -> ...
(define (dir-temp d)
(... (dir-name d) ... (dir*-temp (dir-dirs d)) ... (file*-temp (dir-files d)) ...))
; File -> ...
(define (file-temp f)
(... (file-name f) ... (file-size f) ... (file-content f) ...))
; Dir* -> ...
(define (dir*-temp d*)
(cond
[(empty? d*) ...]
[else (... (dir-temp (first d*)) ... (dir*-temp (rest d*)) ...)]))
; File* -> ...
(define (file*-temp f*)
(cond
[(empty? f*) ...]
[else (... (file-temp (first f*)) ... (file*-temp (rest f*)) ...)]))
(check-expect (dir-find ts 'hang) true)
(check-expect (dir-find ts 'part1) true)
(check-expect (dir-find ts 'part99) false)
(check-expect (dir-find text 'read!) false)
(check-expect (dir-find text 'part2) true)
(check-expect (dir-find docs 'read!) true)
(check-expect (dir-find docs 'draw) false)
; Dir Symbol -> Boolean
; does d have a file with the name filename?
(define (dir-find d filename)
(or (dir*-find (dir-dirs d) filename) (file*-find (dir-files d) filename)))
; File Symbol -> Boolean
; does file f has the name filename?
(define (file-find f filename)
(symbol=? (file-name f) filename))
; Dir* Symbol -> Boolean
; does d* have a file with the name filename?
(define (dir*-find d* filename)
(cond
[(empty? d*) false]
[else (or (dir-find (first d*) filename) (dir*-find (rest d*) filename))]))
; File* Symbol -> Boolean
; does f* have a file with the name filename?
(define (file*-find f* filename)
(cond
[(empty? f*) false]
[else (or (file-find (first f*) filename) (file*-find (rest f*) filename))]))
如果我们为Dir使用此数据定义,则可以使用列表抽象:
; A Dir is a structure:
; (make-dir Symbol [List-of Dir] [List-of File])
; Dir Symbol -> Boolean
; does d have a file with the name filename?
(define (dir-find d filename)
(or (dir*-find (dir-dirs d) filename) (file*-find (dir-files d) filename)))
; File Symbol -> Boolean
; does file f has the name filename?
(define (file-find f filename)
(symbol=? (file-name f) filename))
; Dir* Symbol -> Boolean
; does d* have a file with the name filename?
(define (dir*-find d* filename)
(ormap (λ (d) (dir-find d filename)) d*))
; File* Symbol -> Boolean
; does f* have a file with the name filename?
(define (file*-find f* filename)
(ormap (λ (f) (file-find f filename)) f*))
我们还可以使用本地功能来删除文件名参数
; Dir Symbol -> Boolean
; does d have a file with the name filename?
(define (dir-find d filename)
(local (; Dir -> Boolean
; does d have a file with the name filename?
(define (dir-find-lcl d)
(or (dir*-find (dir-dirs d)) (file*-find (dir-files d))))
; File -> Boolean
; does file f has the name filename?
(define (file-find f)
(symbol=? (file-name f) filename))
; Dir* -> Boolean
; does d* have a file with the name filename?
(define (dir*-find d*)
(ormap dir-find-lcl d*))
; File* -> Boolean
; does f* have a file with the name filename?
(define (file*-find f*)
(ormap file-find f*)))
(dir-find-lcl d)))
实际上,可以进一步简化:
; Dir Symbol -> Boolean
; does d have a file with the name filename?
(define (dir-find d filename)
(or (ormap (λ (d) (dir-find d filename)) (dir-dirs d))
(ormap (λ (f) (symbol=? (file-name f) filename)) (dir-files d))))