2012-07-25 72 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