利用fsharp构建文件结构。
open System.IO
type FileUnit =
| Empty
| File of string * FileAttributes
| Directory of string * FileAttributes * FileUnit
| FDList of seq<FileUnit>
| FileUnit of FileUnit*FileUnit
let rec getFiles4 path =
match DirectoryInfo(path).Exists with
| false -> Empty
| _ -> match DirectoryInfo(path).Attributes &&& FileAttributes.Directory with
| FileAttributes.Directory -> let dlst = match Directory.GetDirectories(path).Length with
|0 -> Empty
|1 -> Directory(path, DirectoryInfo(path).Attributes, Directory.GetDirectories(path).[0] |> getFiles4)
|_ -> FDList(seq{
for elem in Directory.GetDirectories(path) do
yield Directory(elem, DirectoryInfo(elem).Attributes, getFiles4 elem)})
let flst = match Directory.GetFiles(path).Length with
|0 -> Empty
|1 -> File(path, DirectoryInfo(path).Attributes)
|_ -> FDList(seq{
for elem in Directory.GetFiles(path) do
yield File(elem, DirectoryInfo(elem).Attributes)})
FileUnit(flst, dlst)
| _ -> FileUnit(File(path, DirectoryInfo(path).Attributes), Empty )
文件系统是由文件和文件夹组成的。上面的可区分联合引入了几个额外的抽象,对象列表,文件及文件夹组合。回头再来看,解决方案把问题想复杂了。
文件系统最大的特点便是其递归的定义,文件夹含文件和文件夹,可区分联合在这里描述概念再合适不过了。
新的版本
open System
open System.IO
open System.Threading
open System.Threading.Tasks
open System.Diagnostics
#if INTERACTIVE
#time
#endif
type FileUnit =
| FileElem of string * DirectoryInfo
| DirectoryElem of string * DirectoryInfo * seq<FileUnit>
let rec getFiles path =
match Directory.Exists(path),File.Exists(path) with
|false, true -> FileElem(path, DirectoryInfo(path))
|true, false -> DirectoryElem(path, DirectoryInfo(path),
Directory.GetFiles(path) |> Seq.collect (fun it -> [FileElem(it, DirectoryInfo(it))])
|> Seq.append <|
(Directory.GetDirectories(path) |> Seq.collect (fun it -> [ it |> getFiles ])))
|_ -> failwith("can not get file or directory")
let rec getFileList fu (ignoreset:Set<string>)=
seq{
match fu with
|FileElem(name, info) -> yield name, info
|DirectoryElem(name, info, lst) ->
if not (ignoreset.Contains(info.Name)) then
yield name, info; yield! (lst |> Seq.collect (fun x -> getFileList x ignoreset))
}
新版本中文件单元只存在两种情况,文件和文件夹。在进行模式匹配的时候需要做的事也会少一些。getFileList将树形的文件结构铺展为一个1维列表。由于生成列表的过程中使用了Seq对象,所以执行这两个函数几乎是不需要花费时间的,如果有优化也应该在这个时候进行。我在这里过滤了一些需要忽略的文件列表。
原本的想法还是有些乱,改进的空间总是存在的,此为止。