Lambdas and Delegates - why bother?
Written by Mike James   
Wednesday, 12 October 2011

Programming style has evolved - and delegates and lambdas bring us round in a circle. Functions should be objects but if you don't like this idea then you have to invent delegates and lambdas.

 

You must have encountered the idea of either a lambda or a delegate if you have progressed even a little way down the road of becoming a programmer. Put simply, they both provide ways of writing a function that can be used in "clever" ways. The biggest problem with these constructs is figuring out why they exist at all. Oh yes, you can see that where they are used they are needed, and that they make things more elegant. But could there be another way of achieving the same results? This is very much a question of "Where did that come from?"

Stream of consciousness programming

Back in the days when object-oriented programming hadn't been thought of, life was very simple. Programs were written as a long do-this-do-that list. You can think of this as the "stream of consciousness" era of programming. You sat down and wrote the program out as one long list. This may have been simple, but things didn't really work. The long list was impossible to understand after only a few minutes not looking at it. And for another programmer to fathom it - well just don't bother.

Functions and modular programming

The solution to the problem was to invent the function (also known as a procedure or subroutine). You didn't write programs as one long list any more. Instead you broke the program down into sub-tasks and wrote a function to implement each of the subtasks. Then you wrote the full program as a collection of function calls. Of course, if any sub-task turned out to be even slightly complicated, you treated it to the same division process and broke it down into a collection of functions.

This gave programmers a tree-like structure of functions, calling functions, calling functions, and so on. In principle this made the program easier to understand. This was modular programming and the most common form of it was "top-down-modular" programming, which suggested that the right way to build the hierarchy was to start at the top, work your way down till you reached the bottom and then write functions as you worked your way back up the implementation tree. This, plus the idea of block-structured control, was about the high point in programming methods until objects came along and changed everything.

Object-oriented programming

The idea of object-oriented programming is to provide a different way of organizing the code and the data. Instead of code over there and data over here, code and data were bundled together as an object. We all know about objects now, but when they were introduced the idea was hard to swallow. Instead of using top-down modular design, programs were broken up into objects with properties and methods. The properties represented the data and the methods the functions. Notice, however, that there wasn't, and still isn't, any theory of how you should structure an object apart from the idea of inheritance - which is not thought to be the best idea.

Goodbye to functions

A bigger change when objects were introduced was the deprecation of functions. Without really noticing we not only accepted objects but rejected functions. Of course, there were still functions but they were now methods and tied to the object that owned them. This was, and is, a good way to work but occasionally you can see that it isn't quite enough to capture the way we think about computation.

The problem is that in the object-oriented method you can't have a function that doesn't belong to an object. Functions can't float around free like they used to.

Why is this a problem?

Well the answer is that there are lots of times that you naturally think of a function as nothing more than a function. For example, consider the sin function or any similar mathematical function. Most object-oriented languages let you just write something like:

ans=sin(0.5);

as part of an expression. But wait - what is a function doing roaming around on its own without an object to look after it?

Objects with methods

Languages that are stricter tend to introduce a Math object with methods like sin so you then have to write:

ans=Math.sin(0.5);

Yes, it might well be logical but it looks ridiculous and it doesn't do anything to capture the idea that we are working with a function that we consider fundamental in some sense. What is more, if you really think that this logic is good and should be enforced, what about the 0.5? It is a bit of data also out on its own without an object. Presumably the expression should be written:

ans=Math.sin(Math.0.5);

which is now truly silly. Perhaps sin should be a property of the number object? It isn't easy to resolve.

There are other places where the idea of a function seems right all on its own without an object.

In asynchronous programming you often want to define an event handler and so need to define a function outside of an object.

There are lots of situations where you want to specify a function as a parameter to a method call. For example:

MyObject.Map(sin);

to indicate that the sin function should be applied to the data in MyObject. You can try to write this as:

MyObject.Map(Math.sin)

but this misses the fact that you are thinking of sin as an entity in its own right and what do you do about instances? Are you going to restrict function-passing to static objects?

Functions as entities

The key to all of this is that we are really trying to do is to consider a function as an entity in its own right. The obvious way of doing this is to allow a function to be an object. Some languages, like JavaScript, do this directly and allow functions to be full or first-class objects, complete with additional properties and methods of their own. In my opinion this is the best way to do the job as it avoids having to go round a complex route that avoids the idea - but not everyone agrees.

If you allow functions to be objects you can simply allow or create the sin object which has an evaluation operator (). In this case you read

ans=sin(0.5);

as an evaluation, i.e. a call to a default method of the sin object. Similarly, you can pass functions in methods and set event handlers, just as you can pass objects and make references to objects.

Delegates and lambdas

This is neat, but you can avoid the idea of promoting functions to objects by allowing a function type. A delegate is a function type within the type system. Notice it is a type and not an object. To make it into an object you have to create an instance of the type in the usual way, for example:

myfunction= new mydelegate(method);

Notice that the method specified in the constructor is a method that belongs to an object and the instance created simply "wraps" the object method. It is a roundabout way of promoting a method to be a function object. The method is still bound to an object.

So where do lambdas fit it?

Once you have a delegate you really very quickly tire of defining types and methods that are only used after converting to function objects. A lambda is simply a way of defining a function that doesn't belong to an object. That is, a lambda is a complete return to the old function idea in that it is a free-floating function that doesn't belong to an object. In fact a lambda doesn't even have a name - it's an anonymous function with just some input parameters and a body that specifies what to do with the inputs and what to return as a result. A lambda is about the closest thing you can get to the essence of a function. You can use a lambda as part of the instantiation of a delegate and so create a function object that doesn't wrap a method that belongs to an object but to a pure function.

In other words, a delegate plus a lambda simply reinvents the idea of a function object. Occasionally it can even look as if the lambda is a function object in its own right when it is passed as a parameter to a method, but this is just syntactic sugar as a delegate is usually involved to give the lambda some form in terms of signature and return type.

Overall it is so much easier to simply allow functions to be objects.

Banner

Last Updated ( Sunday, 23 October 2011 )
 
 

   
RSS feed of all content
I Programmer - full contents
Copyright © 2014 i-programmer.info. All Rights Reserved.
Joomla! is Free Software released under the GNU/GPL License.