I have a function A similar to this which applies a function B to every file in a directory. Each file has a certain number of “entries”; the function B takes the current total of entries as a parameter and returns the number of new entries found in the current file.
Also, I need to count the number of files processed and display this count each time a file is processed. Due to my imperative background, I came up with 2 mutable variables and a for loop.
let files = Directory.EnumerateFiles sourceDirectory
let mutable numEntries = 0
let mutable numFiles = Seq.length files
let mutable index = 0
for file in files do
printfn "done %d of %d" index numFiles
let numNewEntries = processFile file numEntries
numEntries <- numEntries + numNewEntries
index <- index + 1
So, a few questions:
- How can I write this in a more idiomatic, functional style?
- Can you explain the advantages to a more idiomatic solution? I’m very
new to functional programming and sometimes I don’t see what’s wrong
with my dirty imperative for loops.
Here is a more functional example:
By using
mapiI am able to get access to the index in the loop, eliminating the first mutable variable. The second is eliminated by usingfoldto keep track of the total number of files rather than a mutable variable.The main advantage of this is that without any mutable state it is possible to more easily convert the code to running in multiple threads. Also, as variables are constant, it becomes simpler to reason about the code.