Mark Needham

Thoughts on Software Development

F# vs C# vs Java: Functional Collection Parameters

with 12 comments

I wrote a post about a month ago on using functional collection parameters in C# and over the weekend Fabio and I decided to try and contrast the way you would do this in Java, C# and then F# just for fun.

Map

Map evaluates a high order function on all the elements in a collection and then returns a new collection containing the results of the function evaluation.

Given the numbers 1-5, return the square of each number

Java

int[] numbers = { 1,2,3,4,5};
for (int number : numbers) {
    System.out.println(f(number));
}
 
private int f(int value) {
    return value*value;
}

C#

new List<int> (new[] {1, 2, 3, 4, 5}.Select(x => x*x)).ForEach(Console.WriteLine);

F#

[1..5] |> List.map (fun x -> x*x) |> List.iter (printfn "%d");;

Filter

Filter applies a predicate against all of the elements in a collection and then returns a collection of elements which matched the predicate.

Given the numbers 1-5, print out only the numbers greater than 3:

Java

int[] numbers = { 1,2,3,4,5};
for (int number : numbers) {
    f(number);
}
 
private void f(int value) {
    if(value > 3) {
        System.out.println(value);
    }
}

C#

new List<int> { 1,2,3,4,5}.FindAll(x => x > 3).ForEach(Console.WriteLine);

F#

[1..5] |> List.filter (fun x -> x > 3) |> List.iter (printfn "%d");;

Reduce

Reduce applies a high order function against all the elements in a collection and then returns a single result.

Given a list of numbers 1-5, add them all together and print out the answer

Java

int sum = 0;
int[] numbers = { 1,2,3,4,5};
for (int number : numbers) {
    sum += number;
}
System.out.println(sum);

C#

Console.WriteLine(new[] {1, 2, 3, 4, 5}.Aggregate(0, (accumulator, x) => accumulator + x));

F#

[1..5] |> List.fold_left (+) 0 |> printfn "%d";;

In Summary

I was surprised that we could achieve these results in relatively few lines of Java. The C# and F# versions are still more concise but the Java version isn't too bad. The Apache Commons Library has a class which allows you to write these in a functional way but the need to use anonymous methods means it's not as clean as what you can achieve in C# and F#.

I think there is still a bit of a mindset switch to make from thinking procedurally about these things to thinking in a way that allows you to make the most of functional programming concepts.

Keeping the code as declarative as possible and reducing the amount of state in our code are the most obvious things I have learned so far from playing with F#.

Written by Mark Needham

January 19th, 2009 at 7:24 pm

Posted in .NET, Java

Tagged with , , ,

12 Responses to 'F# vs C# vs Java: Functional Collection Parameters'

Subscribe to comments with RSS or TrackBack to 'F# vs C# vs Java: Functional Collection Parameters'.

  1. [...] F# vs C# vs Java: Functional Collection Parameters (Mark Needham) [...]

  2. [...] F# vs C# vs Java: Functional Collection Parameters – Mark Needham explores three of the common functional programming collection operations in three languages, Map, Reduce and Filter, comparing the implementation in F# with taht in C# and Java [...]

  3. The first extension class I wrote was this:

    public static class IEnumerableExtensions
    {
    public static IEnumerable Each
    (this IEnumerable collection, Func action)
    {
    foreach (T item in collection)
    {
    yield return action(item);
    }
    }

    public static void Each(this IEnumerable collection, Action action)
    {
    foreach (T item in collection)
    {
    action(item);
    }
    }
    }

    This allows you to write the first two C# examples more concisely:

    new[] { 1, 2, 3, 4, 5 }.Select(x => x * x).Each(Console.WriteLine);

    new[] { 1, 2, 3, 4, 5 }.Where(x => x > 3).Each(Console.WriteLine);

    Rik Hemsley

    20 Jan 09 at 7:09 pm

  4. Looks like the site software removed my angle brackets. I'm sure you can figure out what's missing!

    Rik Hemsley

    20 Jan 09 at 7:10 pm

  5. Hi Mark.

    I'm a C# guy so I have a few suggestions about the C# code. Here's my solution to the first two methods Map/Filter.

    Enumerable.Range(1, 5).Select(x => x * x).All(x => { Console.WriteLine(x); return true; });
    Console.WriteLine();
    Enumerable.Range(1, 5).Where(x => x > 3).All(x => { Console.WriteLine(x); return true; });

    The little problem with your methods and those of Rik Hemsley posted in comment is that they create a List or int[]. They allocates memory just to iterate over some int values. In C# we can use Enumerable.Range(int start, int end) which is exactly the same as [start..end] in F#. Because IEnumerable doesn't have ForEach, ( and I don't want to have .ToList().ForEach() ) I'm using "my foreach" – combination of All and return true :)

    For the 3th method I really don't like the Aggregate method extension method of IEnumerable. So with a little bit of cheating we have :

    Console.WriteLine(Enumerable.Range(1, 5).Sum());

    :)

    Petar Petrov

    22 Jan 09 at 6:52 pm

  6. map does NOT evaluate a high-order-function, instead map IS a high-order-function as it calls other functions over a structure.

    h0tzenpl0tz

    23 Jan 09 at 12:36 am

  7. [...] in Java | Tags: scala | by paulosuzart Estava eu vagando pelo meu Google Reader, e encontrei este post falando sobre uma comparação  "for fun" entra Java, C# e F# em alguns aspectos [...]

  8. Hi Mark, I´ve added some comparation to Scala. Try http://raseablog.blogspot.com/2009/01/scala-scala-scala.html to see. It would be very nice to receive your visit.
    Thanks and congratulations for the simple, but very straight nice post.

    Paulo Suzart

    23 Jan 09 at 5:11 am

  9. [...] O post do Paulo que eu li, apesar de também estar no blog dele do link acima, foi lido no Blog do RASEA (um projeto OpenSource que ele toca com alguns amigos) e está aqui. Já o post original com os exemplos iniciais, está aqui. [...]

  10. [...] Blog – Mark Needham’s F# vs C# vs Java: Collection Parameters [...]

  11. The problem with the java version is that they don't are functional style. As your f() method does printing the stuff it is just doing a side-effect and not collecting / filtering values.

    I'd rather write those examples as gathering values in a list / colleciton / enumeration / sequence (lazy). (as you stated in your first paragraph on map). That would be much more interesting because the java version for that is much more noisy than the oder languages:

    int[] numbers = { 1,2,3,4,5};
    Collection result=new ArrayList(5);
    for (int number : numbers) {
    result.add(f(number));
    }

    private int f(int value) {
    return value*value;
    }

    Here the groovy version for map:

    1.upto(5).collect{ it*it }
    and clojure
    (map #(* % %) (range 1 5))

    THAT's concise :)

    If you want to print it directly:
    groovy: 1.upto(5).each{ println it*it }
    clojure: (map #(println (* % %)) (range 1 5))

    Cheers Michael

    Michael Hunger

    30 Apr 09 at 10:15 am

  12. Please don't confuse people by using vastly different data structures in your example. Java uses an array, C# a doubly-linked list, and F# a singly-list list. Use the same data structure, say array.

    F#:

    [| 1..5 |] |> Array.map (fun x -> x * x) |> Array.iter (printfn "%i")

    A

    15 Oct 09 at 6:21 pm

Leave a Reply