在 F# 中:如何获取目录中的文件名列表;预期单位有字符串
In F#: How do I obtain a list of the filenames in a directory; expected unit have string
我刚刚开始使用 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")
这不会编译。它给出了错误:
这个表达式应该有类型
单位
但这里有类型
字符串
我搜索了示例,但找不到任何内容。我显然遗漏了一些简单而基本的东西,但是什么?
由于您是新手,因此更容易修复错误的一件事是考虑像数学语句这样的语句,这些语句可以由更简单的函数构建,但也可以分解。
因此,通过分解您的问题,您可以获得更容易解决的更细粒度的错误。
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)
接受一个类型并且 return 是一个 unit
这意味着 return 什么都没有,在这种情况下打印会起作用,但是您不想 return 什么都不想将目录数组转换为文件名数组。所以 Array.iter
将不起作用,您需要一个数组函数,该函数将一个函数应用于数组中的每个项目,并且 return 是一个新的 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")
我刚刚开始使用 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")
这不会编译。它给出了错误:
这个表达式应该有类型
单位
但这里有类型
字符串
我搜索了示例,但找不到任何内容。我显然遗漏了一些简单而基本的东西,但是什么?
由于您是新手,因此更容易修复错误的一件事是考虑像数学语句这样的语句,这些语句可以由更简单的函数构建,但也可以分解。
因此,通过分解您的问题,您可以获得更容易解决的更细粒度的错误。
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)
接受一个类型并且 return 是一个 unit
这意味着 return 什么都没有,在这种情况下打印会起作用,但是您不想 return 什么都不想将目录数组转换为文件名数组。所以 Array.iter
将不起作用,您需要一个数组函数,该函数将一个函数应用于数组中的每个项目,并且 return 是一个新的 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")