Extending the world

Tagged: functional c# linq extending the world

After a few months I'm back to write on my blog, but to be honest I had a good excuse, since my wife and I have dealt with a move abroad (I'll talk about it separately), which is not exactly something trivial. However, we are slowly returning to normal, and today I managed to get a little time to write this post.

From late August I've been working on an interesting project for a large company, side by side with great guys who every day give me new inputs. One of the things that we most frequently discuss is the functional approach to programming. Nothing new, but unfortunately in the "mainstream" OO world functional programming is often seen as something old, just good for college professors with old PCs, CGA monitors, and weird text editors. Instead, it is a world that is rapidly changing, and it is more and more influencing the development of computer science, and its application to problems of everyday life. But probably this is not enough to decide to abandon the old and comfortable world of OOP for a difficult and perhaps dangerous magical mystery tour...

Game over, then? Not really. The hours spent talking (and especially listening) about themes such as sequences, immutability, lazyness, higher order functions, monads, compositionality, and more, are slowly influencing the way I think and do programming, because most of them are applicable in OOP languages and in languages like C#. The turning point that transformed C# in a "functional space" has been the introduction of Linq. Here you have to remove all the marketing and mainstream technical comunication, which present Linq as the new ORM, a way to make queries directly from code, or in more advanced cases as something for which we can write a query provider that enable us to implement a idiomatic query model. Those are correct views but perhaps limiting, and they do not describe the essence of Linq but only some of the most popular applications. "My" idea now is more and more this one: Linq is an environment in which you can "extend the world" :)

I'll try to write more posts in the coming days about more specific aspects of this statement, now I will focus here on a quick look about one feature: extension methods. They are normally presented as a way to add methods to existing types for which you do not have the source code. In short, a sort of "trick" Microsoft has used to enrich types and interfaces (!) with useful implementations which were not introduced before. The fact that I mentioned the interfaces too should have you wondering about it: how do you add implementations to constructs which by definition do not allow them? Strange, isn't it?

So let's try to reverse the point of view: Linq and its the query syntax are "the world", or rather a "functional" world inside C#, with its required (although not enforced) rules of immutability, absence of side effects, deferred execution, compositionality; then there are the types of the BCL, including interfaces, but also the whole .NET Framework types set, and, why not, our own types, our own interfaces, as well as types and interfaces from any library around. We are envious of IEnumerable and IQueryable, and we'd like so much that our types could join them in Linq query, right? So what can we do? We should begin to write a query provider, shouldn't we? Well, not necessarily, it is often more than enough to write a bunch of extension methods for our types, and here we go, suddenly they can participate in Linq queries! We did not extend our objects, we have extended Linq with them :) This way even the fact that you can "extend" interfaces with implementations makes more sense, because actually you are extending Linq to understand specific interfaces.

Think about it, and next time I will bring some examples and some of related linq links. Just to make you curious, we'll write code like this:

var q = from i in 20.ToMaybe()
        from l in 22.ToMaybe()
        select i + l;

        Assert.IsTrue(q.HasValue);
        Assert.AreEqual(42, q.Value);

var r = from i in ToMaybe.Empty<int>()
        from l in 22.ToMaybe()
        select i + l;

        Assert.IsFalse(r.HasValue);

Published episodes:

  1. Episode 1
  2. Episode 2
  3. Episode 3
  4. Episode 4
  5. Related Material
Add a Comment