Languages - DevSource
DevSource: Microsoft Developer Resource DevSource Home Sponsored by Microsoft Home Add Ons Architecture Languages Techniques Using VS Forums
Home arrow Languages arrow Cigars, Lambda Expressions, and .NET
Cigars, Lambda Expressions, and .NET
By Paul Kimmel

Rate This Article: Add This Article To:

Cigars, Lambda Expressions, and .NET
( Page 1 of 2 )

What do you get when Lambda Expressions meet .NET? In Paul's case, memories of cigars. Find out what how you can now create Lambda Expressions in .NET!

Introduction

I snuck into my Dad's top drawer when I was just about three years old. I found an empty cigar tube—perhaps from a cigar celebrating my birth—took a big whiff and immediately got that queasy feeling referred to as turning green. During my next adventure with a cigar, I almost burned my eyebrows off. Instead of turning me off cigars altogether, I find that into my 40s I enjoy them more and more occasionally.

ADVERTISEMENT

Recently I began smoking Rocky Patel's cigars. If you check the Rocky Patel website there is a quote about the Hollywood lawyer turned cigar maker: "He loves the quality of Padron, the construction of Davidoff, and the consistency of Fuentes." Patel wants to incorporate all of these admirable qualities into his cigars and make them affordable. They're great cigars, so Patel seems to be succeeding.

This is what I like about Microsoft these days. Microsoft is openly recognizing the merit of great ideas and incorporating them into their very affordable products. Lambda Calculus wasn't invented at Microsoft. .NET languages like C# aren't even the first to use Lambda Calculus as the basic for functional programming, but it's a good idea that has a lot of merit and Microsoft is incorporating Lambda Calculus via Lambda Expressions into the .NET framework, C#, and VB.NET.

In this article I am offering a history of Lambda Expressions, how we got to the point where Lambda Expressions make sense, how to write expressions and where you will need them, and finally, a discussion of Currying. I added Currying because a very smart attendee at our Users Group—Glugnet—asked me about currying. I was unfamiliar with the concept, and now I have learned something new too.

Lambda Expression's Rich History

Lambda Expressions didn't just crop up out the ground. They weren't invented to torture VB programmers either. Lambda Expressions is evidence that there are some very bright people in Redmond, they are doing a lot of learning, and some of them may even be humble.

Lambda Expressions are based on Lambda Calculus, which was invented in the 1930s by Alonzo Church and Stephen Kleene. Church and Kleene designed Lambda Calculus to investigate function definition, application, and recursion, and Church used Lambda Calculus to give a negative answer to the Entsheidunsproblem (our old friend the halting problem).

According to Wikipedia, Lambda Calculus can be called the smallest universal programming language, and any computable function can be expressed and evaluated. Maybe, maybe not. More importantly is to what extent Lambda Expressions can be used to express and evaluate any computation we will need. (I have only written a comparatively few expressions, so I can't answer this question. However, I suspect the marketing people at Microsoft can.)

Lambda Expressions are already supported in several languages, including Haskell, OCaml, F#, ALGOL 68, Python, and Ruby.

[Note: The programming Language Haskell was named for Haskell Curry, whose last name was also used to name the technique referred to as Currying although Curry didn't invent the technique.]

Evolution of Lambda Expressions in .NET

Oddly enough, Lambda Expressions support functional programming. In some sense we have come full circle from functional to compositional back to functional, but Lambda Expressions didn't just crop up out of nowhere.

Lambda Expressions in .NET are an evolution from named methods to anonymous methods to the shorter and more concise Lambda Expressions. Named methods are traditional methods with a name, return type, parameters, parameter types, a method body, and statements. Anonymous methods were invented to support really simple event handling. Anonymous methods use the word delegate—hence the alias anonymous delegates—and do not require a method name, or a return, but in every other way are liked-named methods. Anonymous methods are shorthand for named methods. Lambda Expressions are a very shorthand form of named methods, requiring no delegate keyword, no method name, no parameter types, no method body, and no return keyword. Lambda Expressions are very short indeed.

Why do we need Lambda Expressions? Well, because of their very condensed nature Lambda Expressions work very well in the compact world of LINQ. There is a reason hardware gets smaller, processors get smaller and pack on more transistors—the reason is we have to do more with less, less space, time, heat, money, resources, brain power, etc.

Condensing and piling on capability is something we have to do to progress in the programming world. Faster-to-write, smaller elements, that pack in a whole lot more meaning is something that has to happen for software engineers to write tomorrow's software today.

Functional Programming with Lambda Expressions

Lambda Expressions return what are essentially anonymous delegates. C# uses the goes to operator => (or what I refer to as the gosinta) and VB uses the keyword Function. For example, a Lambda Expression that adds two integers would appear like this in C#:

(x, y) => x + y

and in VB9 the same Lambda Expression would like this:

Function(x, y) x + y. 

To pass the Lambda Expression around or call it we need to assign the expression to a variable. For example, to create a variable reference to the expression we can assign it to the generic delegate System.Query.Func like this:

System.Query.Func<int, int, int> Add = (x, y) => x + y;

The first and second int parameter types are for the x and y arguments, and the third int is for the return type. Now we can use Add like any other method: Add(5, 5); returns 10.

We can use implicit parameter type declarations as shown or explicit parameter type declarations indicating that x and y are integers. Listing 1 shows a filtering expression where an IEnumerable<T> instance of people is returned from a List of Person objects that match the criteria LastName == "Swanson".

Listing 1: With one expression p => p.LastName == "Swanson" we can return an enumerable collection of matching Person objects.

using System;
using System.Collections.Generic;
using System.Text;
using System.Query;
using System.Xml.XLinq;
using System.Data.DLinq;
 
namespace LambdaExpressions
{
  class Program
  {
    static void Main(string[] args)
    {
      List<Person> people = new List<Person>
      {
        new Person{ FirstName="Paul", LastName="Kimmel", Age=41},
        new Person{ FirstName="Dena", LastName="Swanson", Age=26},
        new Person{ FirstName="Joe", LastName="Swanson", Age=3},
      };
  
      IEnumerable<Person> results = people.Where(p => p.LastName == "Swanson");
   
      foreach(Person p in results)
        Console.WriteLine(p);
      Console.ReadLine();
    }
   }
  }
  public class Person
  {
    private string firstName;
    public string FirstName
    {
      get
      {
        return firstName;
      }
      set
      {
        firstName = value;
      }
    }

    private string lastName;
    public string LastName
    {
      get
      {
        return lastName;
      }
      set
      {
        lastName = value;
      }
    }
  
    private int age;
    public int Age
    {
      get
      {
        return age;
      }
      set
      {
        age = value;
      }
    }
  
    public override string ToString()
    {
      return string.Format("Name: {0} {1}, Age: {2}", FirstName, LastName, Age);
    }
  }
}

You aren't required to use the temporary variables results for this simple example. You could simply put the method call and expression as the collection in the foreach statement:

foreach(Person p in people.Where(q => q.LastName == "Swanson"))
  Console.WriteLine(p);

We can convert the people.Where statement to a LINQ query, resulting in the following statement:

var linqPeople = from r in people where r.LastName == "Swanson"
        select r;

And, we can iterate through the resulting IEnumerable<Person> result with a foreach statement with linqPeople as the enumerable type

foreach(var subtype in linqPeople)
Console.WriteLine(subtype.LastName);

Without going too far into LINQ, we can use the new keyword in the select predicate to create an anonymous type (or projection), resulting in a completely new type. Here is the preceding LINQ query re-writing to creating a projecting containing just the FirstName and LastName from the Person class.

var linqPeople = from r in people where r.LastName == "Swanson"
  	select new {r.FirstName, r.LastName};

foreach(var subtype in linqPeople)
Console.WriteLine(subtype.LastName);

Although you don't need to know the underlying type (or name) of the projection to use it, you can see the type the compiler emits by opening the executable with Microsoft's ILDASM utility.



 
 
>>> More Languages Articles          >>> More By Paul Kimmel
 



Top Technology Pros One-to-one

All Videos >

Julia explores the Robotics Studio!

Read now >

Messages to Bill Gates!

Read now >

View Now
DevSource RSS FEEDS
XML Want an easy way to keep up with breaking tech news? And the Get DevSource headlines delivered to your desktop with RSS.