Wednesday, March 31, 2010

Power of lambda










Lambda is like sudo make me sandwich:  ^_^
string prefix = "tm";

this.GetAllControls().OfType<CheckBox>()
    .Where(cx => cx.Name.Substring(0, 2) == prefix)
    .ForEach(cx => cx.Visible = false); // do something here in ForEach

The above code reads as: prepare me a list of checkbox which starts with letters tm, and i'll do something on those checkboxes. You can concentrate on things you want to do.

I'll make it myself(without lambda):
string prefix = "tm";

foreach(Control cx in this.GetAllControls())
{
    if (cx is CheckBox && cx.Name.Substring(0, 2) == prefix)
    {
        // payload here, er.. do something here
        (cx as CheckBox).Visible = false; 
    }
    
    // who can be possibly sure that prefix wasn't altered here
    // prefix = "ax";
}

The above code reads as: i'm looking at all controls, check if control is checkbox and starts with letters tm, then i'll do something on that checkbox. And because it is loop, programmers tend to re-read the loop header's condition if all corner cases are covered.



Not only programmers tend to re-read the loop header's condition, they sometimes re-read the whole loop scope, they check if the variable inside for/if conditions are somehow altered on other parts of loop's scope.

With lambda constructs (e.g. OfType, Where), you have that warm and fuzzy feeling that any conditions you fed on lambda functions (e.g. OfType, Where), cannot alter any state(s) in your loop's conditions.

And aesthetic-wise, lambda code looks elegant, very declarative. Compared to its loop cousin, which tend to look ugly if the logic is very nested.

With lambda, you can concentrate on things you want to do, not on how you can do them.

I think .ForEach should be named ActOn :-)

[EDIT]

ForEach apparently is a LinqBridge extension, not defined in .NET 3.5 Framework :-)

Here's how to implement ForEach if you're not using LinqBridge:

static class Helper
{
    public static IEnumerable<t> ForEeach<t>(this IEnumerable<t> source, Action<t> act)
    {
        foreach (T element in source) act(element);
        return source;
    }
}

No comments:

Post a Comment