利用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對象,所以執行這兩個函數幾乎是不需要花費時間的,如果有優化也應該在這個時候進行。我在這裏過濾了一些需要忽略的文件列表。
原本的想法還是有些亂,改進的空間總是存在的,此爲止。