Osborn: What about the addition of anonymous methods? I remember when that [feature] was announced, and I was talking to authors, saying you have to add anonymous methods to [your] text, but not really understanding why [I] was asking them to do that. I'm sure there are use cases for anonymous methods that [people reading this want will want to know about. But also, it's interesting to see how anonymous methods, like generics, are an enabler for new features in C# 3.0].
Hejlsberg: Oh, absolutely. And, you know, honestly, first of all, let's give credit where credit is due. I am not inventing anything completely new here. It's all based on this thing called lambda expressions or lambda calculus or whatever, which has existed in the functional programming space for decades. But somehow, that has never really seen the light of day in a mainstream programming language.
And C# is fortunate enough to be among the first to do that. We're very serious about evolving that, and that's what you're seeing in C# 3.0, where we evolved anonymous methods even further into these things we call lambda expressions now, where we have surrounded them with rich type inference, for instance, so you don't have to say a lot of the stuff that you would have to say manually before.
Hejlsberg: In terms of why they're important, let me illustrate it by an example. In C# 3.0 we're introducing this notion of language-integrated query [LINQ]. And really, what we're doing is we're making it possible to build a query language as an API. You know, out of methods called
GroupBy and whatever. You can see that if a collection has a
Where and a
Select and an
OrderBy, and a
GroupBy method, then you can sort of string them together, and you can build a whole query language out of [them].
But if you were to do that in a language that doesn't support anonymous methods or lambda expressions, then if you think about how you would implement a
Where method, well, it wants to take a predicate as an argument, right? A
test to apply to each element, you know what I'm saying? So I want to say
list.Where(blah), and the
blah I want to pass in is a test.
But it's not like a parameter in the normal sense, because I'm not passing in just a
bool argument, because that obviously would [require that the test] get evaluated up front and then passed in. And I don't want to see
false, I want to be passed the test itself. You know what I'm saying?
Osborn: Yes, you want to pass a procedure to be executed?
Hejlsberg: Yes. And really, what I want is, I want a reference to some code that I can execute, right? I want a function reference or a method reference passed to the
Where operator, such that the
Where operator can run this code for each element that it's trying to test, and then, you know, return to me all of the elements for which this test is true. And if you look at how the
Select operator (i.e.
projection) works, it's the same. It's like, give me an element, and give me a function that can make an element from one thing to another. That's a projection.
OrderBy, it's like, give me something that can compare two elements. Again, it's a piece of code. So really, the thing expressively that has been missing in programming languages is the ability to pass code as parameters.
Osborn: That's the significance--
Hejlsberg: And that is in a nutshell what lambda expressions and anonymous methods allow you to do. And by the way, lambda expressions and anonymous methods are really just two words for the same thing. The only thing that differs is, what does the syntax look like? And the lambda expressions are a further evolution of the syntax. But underneath, they do the same thing. They generate methods. You know, they're in-line methods.