An Example of Functional vs Imperative Programming in C#

Last week I went to a talk presented by Mike Wagg and Mark Needham from ThoughtWorks on Mixing Functional and Object-Oriented Approaches to Programming in C#. Mike and Mark discussed using a functional approach with LINQ to solve problems in C#.

I have come to realise lately that some problems are much better suited to a functional approach than traditional imperative programming. Many problems that involve selecting, filtering or performing actions on a list of items are best suited to functional programming, which can significantly reduce the amount of code required to solve the problem.

Here is a simple example of a problem that is best solved with a functional rather than an imperative approach.

Some businesses advertise their phone number as a word, phrase or combination of numbers and alpha characters. This is easier for people to remember than a number. You simply dial the numbers on the keypad that correspond to the characters. For example, “1-800 FLOWERS” translates to 1-800 3569377.

We will write a simple program that translates a word into a list of corresponding numbers.

phone-keypad

First, let’s start with a dictionary that contains each number and the corresponding characters:

private readonly Dictionary<int, char[]> keys =
            new Dictionary<int, char[]>()
                {
                    {1, new char[] {}},
                    {2, new[] {'a', 'b', 'c'}},
                    {3, new[] {'d', 'e', 'f'}},
                    {4, new[] {'g', 'h', 'i'}},
                    {5, new[] {'j', 'k', 'l'}},
                    {6, new[] {'m', 'n', 'o'}},
                    {7, new[] {'p', 'q', 'r', 's'}},
                    {8, new[] {'t', 'u', 'v'}},
                    {9, new[] {'w', 'x', 'y', 'z'}},
                    {0, new[] {' '}},
                };

Next, we create a Translate method that takes a word and returns an array of corresponding numbers.

With a traditional, imperative approach, we would use for-each loops and if-statements to iterate through characters and populate an array of matching numbers:

public int[] Translate(string word)
{
    ArrayList numbers = new ArrayList();

    foreach (char character in word)
    {
        foreach(KeyValuePair<int, char[]> key in keys)
        {
            foreach(char c in key.Value)
            {
                if(c == character)
                {
                    numbers.Add(key.Key);
                }
            }
        }
    }

    return (int[]) numbers.ToArray(typeof (int));
}

Alternatively, with a functional approach we can use LINQ to select elements from the dictionary and transform the output to an array of matching numbers:

public int[] Translate(string word)
{
    return word.Select(c => 
        keys.First(k => k.Value.Contains(c)).Key).ToArray();
}

And there you have it. Several lines of nested for-each loops replaced with a single line of succinct functional code. Much nicer!

About these ads

4 Responses to “An Example of Functional vs Imperative Programming in C#”


  1. 1 Paul Harrington April 13, 2010 at 8:39 am

    Great post Tim although I would say it’s quite a big jump for those new to functional programming to just convert 3 nested foreach loops & an if statement to that single line of functional code.

    Are there any individual steps you could show that you went through to get to that final state?

  2. 2 timross April 13, 2010 at 8:17 pm

    Hi Paul, thanks for your comment. You are right! I’m now working on a blog post that explains the steps I took to refactor the code.

  3. 3 Blair Conrad August 6, 2010 at 5:25 pm

    I enjoyed the post (and the next one, which dissects the refactoring), I feel like it’s worth mentioning that both the imperative and functional solutions could’ve been made simpler by inverting the keys Dictionary – if it were constructed with a-z and space as keys and 0, 2, 3, …, 9 as values, the original loop collapses to

    public int[] Translate(string word)
    {
    ArrayList numbers = new ArrayList();

    foreach (char character in word)
    {
    numbers.Add(keys[character]);
    }

    return (int[]) numbers.ToArray(typeof (int));
    }

    and the second to

    public int[] Translate(string word)
    {
    return word.Select(c => keys[c]).ToArray();
    }


  1. 1 Refactoring To Functional Code « Tim Ross – .NET Developer Trackback on April 13, 2010 at 9:45 pm

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s





Follow

Get every new post delivered to your Inbox.

%d bloggers like this: