在F#中:如何获取目录中的文件名列表; 预期单位有字符串

Kev*_*oot 2 f# getfiles

我只是从F#开始,所以我想我会尝试一些简单的任务.

这将列出目录中xml文件的完整路径:

System.IO.Directory.GetFiles("c:\\tmp", "*.xml")
|> Array.iter (printfn "%s")
Run Code Online (Sandbox Code Playgroud)

但我只想要文件名,所以我试过:

System.IO.Directory.GetFiles("c:\\tmp", "*.xml")
|> Array.iter (System.IO.Path.GetFileName)
|> (printfn "%s")
Run Code Online (Sandbox Code Playgroud)

这不会编译.它给出了错误:

该表达式应该具有类型单元,
但这里有类型字符串

我搜索了一些例子但找不到任何东西.我显然缺少一些简单而基本的东西,但是什么呢?

Guy*_*der 11

既然你是新手,那么让错误修复错误的一件事就是想到像数学语句这样的语句可以用更简单的函数构建,但也可以分开考虑.

因此,通过分解您的问题,您可以获得更容易解决的更细粒度的错误.

System.IO.Directory.GetFiles("c:\\tmp", "*.xml")
|> Array.iter (System.IO.Path.GetFileName)
|> (printfn "%s")
Run Code Online (Sandbox Code Playgroud)

被分解为

let directoryArray = System.IO.Directory.GetFiles("c:\\tmp", "*.xml")
let nameArray = Array.iter (System.IO.Path.GetFileName) directoryArray
(printfn "%s") nameArray 
Run Code Online (Sandbox Code Playgroud)

现在错误应该更容易理解

如果我们看看它的签名Array.iter是否iter : ('T -> unit) -> 'T [] -> unit 我们看到它需要一个('T -> unit)带有类型的函数并返回一个unit意味着什么都不返回,在这种情况下打印会起作用,但是你不想返回任何你想转换的数组目录到文件名数组.所以Array.iter不会工作,你需要一个Array函数,将一个函数应用于数组中的每个项并返回一个新的Array,Array.map这样做map : ('T -> 'U) -> 'T [] -> 'U []为了更好地理解数组函数,看看它们如何工作,可以添加一个lambda function.

同样地(printfn "%s"); 可以添加一个lambda函数来传递一个值.

let directoryArray = System.IO.Directory.GetFiles("c:\\tmp", "*.xml")
let nameArray = Array.map (fun x -> (Path.GetFileName(x))) directoryArray
Array.iter (fun x -> printfn "%s" x) nameArray
Run Code Online (Sandbox Code Playgroud)

现在我们可以使用简化语句 |>

System.IO.Directory.GetFiles("c:\\tmp", "*.xml")
|> Array.map (fun x -> (Path.GetFileName(x)))
|> Array.iter (fun x -> printfn "%s" x)
Run Code Online (Sandbox Code Playgroud)

并通过删除再次简化 lambdas

open System.IO

Directory.GetFiles("c:\\tmp", "*.xml") 
|> Array.map Path.GetFileName 
|> Array.iter (printfn "%s") 
Run Code Online (Sandbox Code Playgroud)