What is this 'Lambda' everyone keeps speaking of? A lot of people seem to love it, but all I can gather from it is it is just a way of cramming lots of lines of code into a single expression.
Can someone please enlighten me on its true value?
What is this 'Lambda' everyone keeps speaking of? A lot of people seem to love it, but all I can gather from it is it is just a way of cramming lots of lines of code into a single expression.
Can someone please enlighten me on its true value?
"A lambda expression is an anonymous function that can contain expressions and statements, and can be used to create delegates or expression tree types.
All lambda expressions use the lambda operator =>, which is read as "goes to". The left side of the lambda operator specifies the input parameters (if any) and the right side holds the expression or statement block. The lambda expression x => x * x is read "x goes to x times x."
from MSDN
"Lambda" maybe just too few. Take a look at Lambda calculus. It's useful in functional programming.
And functional programming is yet another programming paradigm (like procedural, or object-oriented).
You'll find all you need to know for a start here:
Lambda expressions
Lambdas in .NET are quite often referred to as "syntactic sugar". They do not directly affect the functionality however they make the language easier for people to use.
When you have understood the power of using them I am sure you will find that you will be writing less code compared to the old style way using delegates / anonymous methods.
For a full explanation about Lambda expressions, also check out Wikipedia. (Scroll down to the Lambda calculus and programming languages part.) Lambda expressions aren't that new and they aren't just part of C# but something that has been introduced to computing almost 80 years ago! Lambda expressions are the basis for functional programming.
It's value? Well, considering that it's actually quite old, I would say: very valuable for anyone doing calculations.
If you are into Java, you've heared a lot about lambdas or closures in the last couple of month, because there were different proposals for adding this feature to Java 7. however, I think the comitee dropped it. One of the proposals is from Neal Gafter and explained in great detail here: javac.info. This helped me understanding the use cases and advantages (especially over inner classes)
I'm not sure if the "true value" of having a language support lambda expressions lies with the lambda expressions themselves, but rather the language having functions as first class objects (or at least close to).
The term "lambda" is used to refer to an anonymous function, usually a closure. They're useful because they allow you to write functions that use other functions without bloating your code unnecessarily. For example, in Ruby:
(1..100).select {|num| num % 2 == 0}
This will create an array containing the even numbers between 1 and 100. We don't have to write out an explicit loop — the select method takes a function that it uses to test the values, so all we need is our custom logic. This allows us to greatly customize the method with practically no effort or overhead. Basically, we can compose functions out of smaller functions.
That's just an easy example of what they can do. The ability to pass functions as data is really powerful and functional language programmers routinely do some really amazing things with it.
Look no further: http://www.youtube.com/watch?v=y2KIxMQro-w
zoom to about 1:05.
Dr Dobbs Journal has a useful article introducing lambda expressions (within the context of C++ but I think you can apply the principles to any language).
As the article says: "A lambda expression is a highly compact expression that does not require a separate class/function definition."
So using the examples of listings 1 & 2 from DDJ instead of writing:
std::for_each( vec.begin(), vec.end(), print_to_stream<std::string>(std::cout));
Which requires a separate class definition like:
template <typename T, typename Stream> class print_to_stream_t {
Stream& stream_;
public:
print_to_stream_t(Stream& s):stream_(s) {}
void operator()(const T& t) const {
stream_ << t;
}
};
template <typename T,typename Stream>
print_to_stream_t<T,Stream> print_to_stream(Stream& s) {
return print_to_stream_t<T,Stream>(s);
}
Using the Boost lambda library this can become:
std::for_each(vec.begin(),vec.end(),std::cout << _1);
Which keeps the definition inline.
The article also explains some more applications of lambda expressions.
I think a key point in the DDJ article is "Typically, lambda expressions are used when small and not overly complex functions are needed at the call site. If the function were nontrivial, you wouldn't want a lambda expression but a normal function or a function object."
If you've ever worked with functions/methods that use function pointers, delegates, strategy or observer pattern/event handling, and thought to yourself "I'm writing this whole function just to use it just once - to pass it to this method; I wish I could just write it in place, rather than clutter my code" - that's where you might use Lambda functions. Languages that support this construct also usually heavily take advantage of the concept of passing functions as parameters, particularly in regards to working with lists (first class functions and higher order functions). This is especially true for functional languages, which rely on function composition rather than memory modification for computations. In some cases (in languages such as Python), the use of lambda functions with list comprehensions is also considered more readable than the equivalent foreach loop.
Yes, it is just a way of cramming lots of lines of code into a single expression. But being such an efficient cramming, it enables some new ways of structuring your program.
Often one would avoid writing delegates or callbacks and revert to procedural style simply because it's too much work to declare new functions or classes for a single expression.
Lambda expressions make it worthwhile to use callbacks even for tiniest tasks, which might make code more clear. Might not.
Simply put, a lambda is a function without a name, or an anonymous function. A small piece of executable code, that can be passed around as if it were a variable. In JavaScript:
function () {}; // very simple
Let's see now some uses for these lambdas.
Lambdas may be used to abstract away boilerplate code. For example loops. We're used to write for
and while
loops all day long. But this is code that does not be written. We could extract the code inside the loop, the most important part of the loop, and abstract away the rest:
for (var i=0; i<array.length; i++) {
// do what something useful with array[i]
}
by using the forEach
of array objects, becomes:
array.forEach(function (element, index) {
// do something useful with element
// element is the equivalent of array[i] from above
});
The above abstraction may not be that useful, but there are other higher order functions, like forEach
, that perform much more useful tasks. For example filter
:
var numbers = [1, 2, 3, 4];
var even = [];
// keep all even numbers from above array
for (var i=0; i<numbers.length; i++) {
if (numbers[i] % 2 === 0) {
even.push(numbers[i]);
}
}
alert(even);
// Using the filter method
even = [1, 2, 3, 4].filter(function (number) {
return number % 2 === 0;
});
alert(even);
In some environments, in which the concept of event is available, we could use lambdas to respond to events that may happen at some point in time.
window.onload = function () {
alert("Loaded");
};
window.setTimeout(function () {
alert("Code executed after 2 seconds.");
}, 2000);
This could have been done in some other ways, but those are rather verbose. For example, in Java there's the Runnable
interface.
Until this point, we only used lambdas for its syntactic sugar capabilities mostly. But there are situations where lambdas can be much more useful. For example we may have functions that return lambdas. Let's say we have a function that we want its return values to be cached.
var users = [];
var getUser = function (name) {
if (! users[name]) {
// expensive operations to get a user. Ajax for example
users[name] = user_from_ajax;
}
return users[name];
};
Later on, we may notice that we have a similar function:
var photos = [];
var getPhoto = function (name) {
if (! photo[name]) {
// expensive operations to get a user. Ajax for example
photos[name] = photo_from_ajax;
}
return photos[name];
};
There's clearly a pattern in there, so let's abstract it away. Let's use memoization.
/**
* @param {Array} store Data structure in which we cache lambda's return values
* @param {Function} lambda
* @return {Function} A function that caches the result of calling the lambda param
*/
var memoize = function (store, lambda) {
// return a new lambda
return function (name) {
if (! store[name]) {
// Execute the lambda and cache the result
store[name] = lambda(name);
}
return store[name];
};
};
var getUsers = memoize([], function (name) {
// expensive operations to get a user. Ajax for example
});
var getPhotos = memoize([], function (name) {
// expensive operations to get a photo. Ajax for example
});
As you can see, by using lambdas, we were able to abstract away the caching/memoization logic. If for the other example there were some workarounds, I believe that this particular problem is hardly solved using other techniques. We managed to extract some important boilerplate code into a single place. Not to mention that we got rid of the users
and photos
global variables.
Looking at your profile I see that you're mostly a Python user. For the above pattern, Python has the concept of decorators. There are lots of example on the net for memoization decorators. The only difference is that in Python you most likely have a named nested function inside that decorator function. The reason being that Python only support single-expression lambdas. But the concept is the same.
As an example of Python lambda use. The above code in which we filtered even numbers can be represented in Python like this:
filter(lambda x: x % 2 == 0, [1, 2, 3, 4])
Anyway, lambdas are not that powerful without closures. Closures is what makes the concept of lambdas so powerful. In my memoization example I have used closures to create a closure around the store
param. This way, I have access to that param even after the memoize
function has returned its result (a lambda).
'lambda' qua word is terminology from the days when computer science types were as likely to be trained in math or logic than have a computer science degree. Some of them cooked up a paradigm called 'functional programming', quite different from imperative and quite powerful too. AFAIK that is the milieu where the term came into use.
Mathematicians and logicians are given to using weird words.
'lambda' sounds really esoteric - as if they are a very strange and special thing. Really, if you write JavaScript for a web browser application and use the "var foo=function() {...}" idiom, you've been using lambda functions all along.
Check out this article to learn about different concepts in lamba expression: http://developergeeks.com/article/41/lamda-expression-concept-in-net---explained