我刚开始使用F#,所以我想我会尝试一些简单的任务。
这列出了目录中xml文件的完整路径:
System.IO.Directory.GetFiles("c:\\tmp", "*.xml")
|> Array.iter (printfn "%s")
但我只想要文件名,所以我试过了:
System.IO.Directory.GetFiles("c:\\tmp", "*.xml")
|> Array.iter (System.IO.Path.GetFileName)
|> (printfn "%s")
这不会编译。它给出了错误:
预计此表达式具有类型
单元
但这里有类型
字符串
我搜索了一些例子但找不到任何东西。我显然缺少一些简单而基本的东西,但是什么呢?
答案 0 :(得分:9)
因为你是新手,所以更容易修复错误的一件事是想到像数学陈述这样的陈述,这些陈述可以用更简单的函数构建,但也可以分开考虑。
因此,通过分解您的问题,您可以获得更容易解决的更细粒度的错误。
System.IO.Directory.GetFiles("c:\\tmp", "*.xml")
|> Array.iter (System.IO.Path.GetFileName)
|> (printfn "%s")
被分解为
let directoryArray = System.IO.Directory.GetFiles("c:\\tmp", "*.xml")
let nameArray = Array.iter (System.IO.Path.GetFileName) directoryArray
(printfn "%s") nameArray
现在错误应该更容易理解
如果我们查看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
现在我们可以使用|>
System.IO.Directory.GetFiles("c:\\tmp", "*.xml")
|> Array.map (fun x -> (Path.GetFileName(x)))
|> Array.iter (fun x -> printfn "%s" x)
并删除lambdas
open System.IO
Directory.GetFiles("c:\\tmp", "*.xml")
|> Array.map Path.GetFileName
|> Array.iter (printfn "%s")