Having been using LINQ since it first came out, I feel that I’m only now starting to really appreciate some of the applications for declarative coding. When I first heard about it, I was pretty sceptical about it, but I’m actually becoming a pretty big fan of it now. Here’s an example that I thought about a few days ago.
Someone asked me to write some code that would print out the first five answers of the first five times’ tables e.g.
1 x 1 = 1, 1 x 2 = 2, 1 x 3 = 3, 1 x 4 = 4, 1 x 5 = 5
2 x 1 = 2, 2 x 2 = 4, 2 x 3 = 6, 2 x 4 = 8, 2 x 5 = 10
I actually initially thought “let’s do this with LINQ” but on the spur of the moment went back to my imperative coding roots and fumbled around with a couple of nested for loops… it probably ended up looking something like this:
(Imagine that limit is a const int of 5)
(Please ignore the fact that there would be an extra comma at the end of each line…)
Anyway… I got back to thinking about how I could have written this in LINQ and (pretty quickly) ended up with this:
If you’re not used to working with LINQ queries and / or projection, this may seem a little strange to you. But it’s pretty simple really – the first two lines just build up a 5 x 5 matrix (remember that limit = 5), and then we simply apply the function to create a new anonymous type over it.
Takes up slightly more code, but to my mind, at least from a readability perspective, offers two main benefits over the imperative version: –
Clear separation between the logic / construction of the dataset, and the effort of printing them out. You could change the source data without any work required on the bit of code to print it out. Of course you could do that in the first example, but it’s not natural to think of that – when writing with for loops I just seem to naturally mash the two together parts into one.
Clarity of program flow. In the second example, it’s clear why we’re printing Console.WriteLine (), compared to the previous example where the WriteLine () is there almost implicitly at the end of the outer for loop. You can figure it out easily enough – but the second example, to me at least conveys the intent better.
I actually also went one step further and took the second example to its logical conclusion and put the number.EndOfLine conditional within the anonymous type itself (as well as the Console.WriteLine bit):
I’m not sure whether I like this or not – in some ways it’s quite elegant, but the amount of code has risen again, plus I’m not sure whether the practice creating anonymous methods as a result of a conditional, as a property of an anonymous type is really that great an idea vis a vis readability or not 🙂