Code for thought: Linq? Functional Approach?

4 replies [Last post]
Kayin
Offline
SX Retired
Joined: 2008/10/09

Take this example of basic filtering. (examples in C# - because it's most readible shut up)

Say you have a list of strings and you want to remove all strings that start with the letter "s" - case sensitive.
Normal solution: Iteration

List<string> ListOfStrings = GetFromSomewhere();
List&lt;string&gt; NewList = new List<string>()
foreach (String str in ListOfStrings)
{
     if(!str.StartsWith("s"))
     {
           NewList.Add(str)
     }
}

It's such a simple, common, and basic thing you want to do very often. Yet you have to go through the tedious work of setting up the for loop, creating the new list, defining the conditions...etc. Takes about a minute. A waste of a minute if you ask me.

Check out an alternative solution using Linq. Linq is a really cool extension that brings SQL like querying out of the database and into the programming language:

List&lt;string&gt; ListOfStrings = GetFromSomewhere();
List&lt;string&gt; NewList = (From str In ListOfStrings Where !str.StartsWith("s") );

One line, does the exact same thing as the above and took about 10 seconds to type out. I personally like this approach, however when doing anything more complicated the Query expression becomes equally as complicated. It's a downside that makes you feel like you're writing SQL instead of code. That's sort of the point though.

How about this, a functional approach:

List&lt;string&gt; ListOfStrings = GetFromSomewhere();
List&lt;string&gt; NewList = ListOfStrings.Filter(
     delegate(string str)
     {
           return str.StartsWith("s");
     }
);

This utilizes an anonymous delegate. You can achieve the same thing with function pointers. Essentially I create a function to perform some task and then pass that method into a larger more comprehensive method.

In this case the task of the anonymous method is to determine if an item in the list should be 'selected'. The larger comprehensive method's job is to take the 'selected' items (defined by the smaller method) and remove them from the list.

This approach is a little more effort than the Linq query but is far more scalable as you can stack methods upon methods in a very functional sort of way.

Edit: should also point out, 1 line anonymous delegates can be replaced by lamda functions.

List&lt;string&gt; ListOfStrings = GetFromSomewhere();
List&lt;string&gt; NewList = ListOfStrings.Filter( string str =&gt; return !str.StartsWith("s") );

-K