F#查找过去5天内修改的子目录中的所有文件

时间:2015-04-14 14:16:19

标签: f#

我对F#相当新,所以请保持温和。我试图用函数式编写代码来查看过去5天内修改过的所有文件的目录(和子目录),然后对这些文件执行某些操作(此时只是将名称写入控制台)

我的代码是:

open System.IO

let rec getAllFiles dir pattern =
    seq { yield! Directory.EnumerateFiles(dir, pattern)
          for d in Directory.EnumerateDirectories(dir) do
              yield! getAllFiles d pattern }

let printMe x = printfn "%A" x

let hasChangedRecently fileName =
    let myFile = System.IO.FileInfo(fileName)
    let f myFile = function
    | myFile when myFile.LastWriteTime >= System.DateTime.Parse "10-04-2015" -> printMe MyFile.Name
    | _ -> ()

    f fileName

[<EntryPoint>]
let main argv =
    getAllFiles @"c:\temp" "*.xml"
    |> Seq.iter hasChangedRecently

    System.Console.ReadKey() |> ignore
    0 // return an integer exit code

在hasChangedRecently块中出错了。

错误是:

myFile.LastWriteTime
Lookup on object of indeterminate type based on information prior to this program point. A type annotation may be needed prior to this program point to constrain the type of the object. This may allow the lookup to be resolved.

MyFile.Name
The namespace or module 'MyFile' is not defined

|> Seq.iter hasChangedRecently
Type mismatch. Expecting a
string -> unit    
but given a
string -> 'a -> unit    
The type 'unit' does not match the type ''a -> unit'

我很确定这些是基本的错误,但会真诚地感谢一些指导。

2 个答案:

答案 0 :(得分:5)

我会将hasRecentlyChanged更改为string -> bool函数并使用它过滤文件,然后使用单独的函数来打印文件。

let hasChangedRecently fileName =
    let myFile = System.IO.FileInfo(fileName)
    myFile.LastWriteTime >= System.DateTime.Parse "10-04-2015"

let printFile file =
    printfn "%s" file

main

getAllFiles @"c:\temp" "*.xml"
|> Seq.filter hasChangedRecently
|> Seq.iter printFile

此外,如果您愿意,可以使用.NET内置的getAllFiles来避免SearchOption.AllDirectories递归:

Directory.EnumerateFiles(dir, pattern, SearchOption.AllDirectories)

答案 1 :(得分:1)

我认为您也可以像这样重写hasChangedRecently(并让它打印结果)

let hasChangedRecently fileName =
    match  System.IO.FileInfo(fileName) with
    | myFile when myFile.LastWriteTime >= System.DateTime.Parse "10-04-2015" -> printfn "%s" myFile.Name
    | _ -> ()

如果你想使用函数,你将以某种方式帮助编译器推断类型。在这种情况下,您可以写:

let hasChangedRecently fileName =
    let analyze: (System.IO.FileInfo -> _) = 
        function 
        | x when x.LastAccessTime > System.DateTime.Parse "10-04-2015" -> printfn "%s" x.Name 
        | _ -> ()
    analyze System.IO.FileInfo(fileName)

正如Vandroiy在他的评论中所说的那样,function对未命名的论证进行了模式匹配。在这里,我们只是将analyze的类型定义为在参数中获取FileInfo并返回任何内容的函数。

相关问题