Sunday, September 27, 2009

Darrell Hawley on IronPython and LINQ

Darrell Hawley is a Microsoft MVP with an interest in IronPython. We've featured some of his previous writings here, here and here.

He's made a couple of posts on using LINQ from IronPython. LINQ is a .NET feature that give first class syntax in C# to queries. Under the hood LINQ is implemented as a series of extension methods and classes. In it's basic form LINQ is similar to Python generator expressions. As well as working on objects LINQ expressions can be used to generate SQL queries. A Python equivalent would be the Dejavu project.

LINQ is a language feature where multi-line lambdas really show their power; something that isn't possible in Python of course where lambda functions are restricted to a single expression. The power of LINQ causes Darrell to describe it as:
Python developers would be better served to think of LINQ as wrappers around the map, filter and reduce functions. In fact, LINQ is not much different than the “recipes” found in the official itertools documentation.

The first of Darrell's blog entries on the topics is actually a correction to a comment about LINQ Darrell made in a Devlink presentation. He follows it up with a more general look at what LINQ is capable of and how to use it from IronPython - either using the LINQ classes or achieving similar effects with Python libraries.
 You have to remember that IronPython does NOT support extension methods and since LINQ is pretty much a collection of extensions methods, there’s a problem. Why this design decision? Because in order to support extension methods, the IronPython team would have had to make changes to the core language which would have, of course, been rather un-Pythonic. This means that the code for consuming LINQ is going to be somewhat messy. The following snippet gives an example of consuming the Average function of the Enumerable object.

clr.AddReferenceToFileAndPath(r"C:\folder\System.Core.dll")
from System.Linq import Enumerable
from System import Func

list = [1,2,3,4,5]

print Enumerable.Average[object](
    list, Func[object, int](lambda x:x))
So the question still stands: does IronPython need LINQ? In my last post, I described how to use LINQ from an IronPython application and implied that I didn’t think it was the best idea. Don’t get me wrong, I really enjoy writing LINQ statements, I just don’t think LINQ fits well with IronPython. Why not? The first problem I have with the IronPython/LINQ combination is put on prominent display in this code sample.

print Enumerable.Average[object](
    list, Func[object, int](lambda x:x))

If you are a static language aficionado, you probably are wondering what the problem is. If you’re a Python developer, however, the fact that I’m explicitly naming the “object” and “int” types is sending up giant, red flags. Python folks don’t really care what type of object it is they’re using, they only want to know what the object can do and what it contains (i.e., duck-typing). It’s much easier – and more readable - to simply write a completely Python version of the Average function.

No comments:

Post a Comment

Note: only a member of this blog may post a comment.