Archive

Archive for the ‘LINQ’ Category

F# vs C#. Fold and Aggregate

May 13, 2013 2 comments

Suppose you need to write a script that finds n files, all called based on some pattern, say “c:\temp\my_file_x.txt”, where “x” is replaced by a range of numbers [1..30] for instance, reads the content of these files and glues them together. Suppose also that the files are very small, so you can keep them in memory all at once. Also, it should be solved in one line (except for auxilaires: defining variables, writing out the results).

One-line solutions exist both in F# and C#. Which one is prettier? I vote for F#.

Here is the C# code:


string templ = @"C:\temp\my_file_";

var content =
 Enumerable.Range(1, 30)
     .Aggregate(
        new List<string>(),
        (a, e) =>
           {
               a.AddRange(File.ReadAllLines(templ + e.ToString() + ".txt"));
               return a;
            });

File.WriteAllLines(templ + ".txt", content);

And here is the F# version (of just the relevant part):

let content =
  [1..30]
  |> List.fold (
    fun content i -> 
      content @ 
      (File.ReadAllLines(fun i -> templ + i.ToString() + ".txt") |> Array.toList)
    ) []

You can accomplish almost anything with fold() and its C# Linq equivalent Aggregate().
So first we create a range, (1..30) (note here, that although [1..30] and Enumerable.Range(1, 30) generate sequences of numbers from 1 to 30, their semantics are different, so [0..30] and Enumerable.Range(0, 30) generate different sequences: the latter generates a sequence of numbers 0..29).

Then we fold the range of numbers into a list of lines (we could have just kept appending the text, not lines, but it is not all that important for this macro, and we want to make sure we start each new addition from a new line), by reading the files and gluing the results together

Categories: C#, F#, LINQ Tags: ,