2012-07-25 54 views
0

我有一个函数A类似于这个,它将一个函数B应用到目录中的每个文件。每个文件都有一定数量的“条目”;函数B将当前的条目总数作为参数,并返回在当前文件中找到的新条目的数量。如何让这段代码更具惯用的F#?

此外,我需要统计处理的文件数,并在每次处理文件时显示此计数。由于我的命令背景,我想出了2个可变变量和一个for循环。

所以,有几个问题:

  • 我怎么可以这样写的更地道,实用的风格?
  • 你可以解释一个更习惯解决方案的优点吗?我很新功能编程 ,有时我看不出有什么不对 与我的循环脏必要。
+3

这对于[CodeReview.SE](http://codereview.stackexchange.com/)更合适。无论如何,'fileCounter'声明在哪里,为什么最终将'unit'分配给'files'? (是'文件'打算成为一个函数吗?) – ildjarn 2012-07-25 02:01:23

+0

对不起格式是误导和fileCounter声明丢失。我编辑了代码来解决这个问题。 – Asik 2012-07-25 02:19:43

回答

6

这里有更多的功能例如:

let files = Directory.EnumerateFiles sourceDirectory 
let numFiles = Seq.length files 
files 
|> Seq.mapi (fun idx file -> (idx,file)) // Get access to the index in a loop 
|> Seq.fold (fun numentries (index,file) -> 
     printfn "done %d of %d" index numFiles 
     numentries + (processFile file numFiles) 
     ) 0 

通过使用mapi我能够获得访问索引的循环,消除第一可变变量。第二个是通过使用fold跟踪文件的总数而不是可变变量来消除的。

这样做的主要优点是没有任何可变状态,可以更容易地将代码转换为在多个线程中运行。另外,由于变量是不变的,因此代码的推理变得更简单。

+0

谢谢。我修复了一些有点误导性的代码,错过了一个声明:你能否更新你的答案以反映它? fileCounter(实际上是numEntries)与numFiles不同。 numFiles是目录中的文件总数,用于打印“done x out numFiles”。 fileCounter(重命名为numEntries)是在文件中找到的条目的总数。 – Asik 2012-07-25 02:23:14

+0

@Dr_Asik - 已更新 – 2012-07-25 02:41:49

+0

接受您的回答后,您至少应该编辑它。 ; - ](提示 - '目录。EnumerateFiles'不返回数组。) – ildjarn 2012-07-25 22:31:23

1

假设你最终后是是numEntries终值,那么这是我的看法:

let getNumEntries sourceDirectory = 
    Directory.GetFiles sourceDirectory 
    |> fun files -> (0, 0, files.Length), files 
    ||> Array.fold (fun (index, numEntries, numFiles) file -> 
     printfn "done %d of %d" index numFiles 
     index + 1, numEntries + processFile file numEntries, numFiles) 
    |> fun (_,numEntries,_) -> numEntries 

如果你之后processFile是副作用,而不是最终的numEntries值的时候,然后用ignore代替fun (_,numEntries,_) -> numEntries


你能解释的优势,以更地道的解决方案?我对函数式编程非常陌生,有时候我看不出循环中的脏命令有什么问题。

除了主观,这是相当广泛的,并已在其他多个答案更彻底地回答比我在这里可以做的。

+0

该函数实际返回单位:“processFile”将所有有用的工作作为副作用(将条目写入磁盘)。 我的问题不是一般的函数式编程,而是特定的代码片段。我知道一般的想法,但我试图找到具体的例子来推动这一点。当然,为什么这7行代码比我的9行代码更好,这并不是一个太宽泛的问题。 – Asik 2012-07-25 02:57:52

+0

@Dr_Asik:如果你想让函数返回'unit',那么用'ignore'替换fun(_,numEntries,_) - > numEntries'。即使问这个特定的代码和你发布的代码的范围并不是太广泛,它肯定是主观的,根据定义它不适合SO。无论如何,就像我说的那样,在回答你所问的问题上有几十个答案,更不用说其他数千篇在线文章了。 – ildjarn 2012-07-25 03:00:10