Lambda Expressions via Sub Routines

Introduction

I love Lambda expressions. I like the way it rolls off the tongue. I like the concise cleverness of them. I like the mathematics based history, and they are just plain fun to write. (Well, if you are a geek like me.) The great thing about being a geek is that Billionaire boy genius Bill Gates made it cool to be nerdy. (Nerds!)

There was a short circuit in the first release of Lambda expressions for VB though. Originally VB lambdas only supported Functions. That is, you had to return a value. As we all know sometimes you just want the code to do something. Fortunately this has been corrected in VB2010. Let's take a peek.

Lambda Expression Subs

The simplest explanation for Lambda expressions is that they are condensed methods. A lot of the explicit information you add to a regular function or sub is just left on the cutting room floor for Lambdas, but they are really just functions. A regular sub routine has optional modifiers like public or shared, the sub or function keyword, the method name, optional parameter types and names, a return type for functions, the method body, and the end block. This is simply a lot of information that can be inferred from a block of code's usage.

    Sub Main()

    End Sub

A Lambda expression doesn't use modifiers, the Sub or Function keyword is used. Parameter types can be used or not and pretty much everything else is left on the cutting room floor; that is, things like parameter types can be and are inferred from how a parameter is used. Another nice feature of Lambdas in VB2010 is support for multiline Lambda expressions. A Lambda expression is generally a short method, but sometimes you need more than one statement even in a Lambda.

Suppose for arguments sake that you want to add some custom tracing to an application. Originally you decide to send information to the Console. So, everywhere you want tracing you write Console.WriteLine(information). Now suppose you decide you want to send trace information to the Debug window. Obviously you could do a global search and replace, replacing all instances of Console.WriteLine with Debug.WriteLine, you could use a global wrapper method and replace the single line of code, or you could use a Lambda. Simply implement the Lambda to write the statement, call the Lambda everywhere you want tracing to occur. To change the behavior change just the Lambda expression. Listing 1 shows you an implementation of a Lambda expression that sends output to the Debug window.

Module Module1

    Sub Main()

      Dim tracer = Sub(str) Debug.WriteLine(str)

      tracer("Jello Mold")

      Console.ReadLine()

    End Sub

End Module
Listing 1: Implementing a Lambda expression sub

Now this is probably the weakest use of a Lambda expression, but you get the idea. See how short Lambda expressions are?

Probably the primary reason for Lambda expressions is to support the underpinnings of LINQ (Language INtegrated Query). LINQ is a short query language that uses a lot of delegates to process parts of a query, and a compact way to implement a delegate is through a Lambda expression. There is a lot of information on delegates and LINQ, including this column (VB Today and my book LINQ Unleashed), so I won't go any farther down this road for now. Here is an example--see Listing 2--of a multiline Lambda expression passed around and used willy nilly.

Imports System.Reflection

Module Module1

    Sub Main()

      Dim tracer = Sub(str) Debug.WriteLine(str)

      tracer("Jello Mold")

      Dim dumper = Sub(obj)
                     Dim info As PropertyInfo()
                     info = obj.GetType().GetProperties()
                     For Each prop In info
                      Console.WriteLine("{0} :{1}", prop.Name, 
                        prop.GetValue(obj, Nothing))
                     Next
      End Sub

      dumper(Assembly.GetExecutingAssembly())
      dumper(dumper)

      Dim use As UseLambda = New UseLambda()
      use.UseDumper(dumper)

      Console.ReadLine()

    End Sub

End Module


Public Class UseLambda

  Property Test As Integer

  Sub UseDumper(ByVal action As Action(Of Object))

    action(Me)

  End Sub

End Class

Listing 2: A Lambda expression that implements an object state dumper

The dumper variable is actually a Lambda expression that uses reflection to read a property's state. That's all it does. The first use dumps properties for the executing assembly. The second use dumps the dumper, and the third use passes the Lambda expression to another object and that object uses it (see UseLambda).

The key to using Lambda expressions for dynamic programming--where you pass them around is to know the type that a particular Lambda expression returns. A Lambda sub routine is actually returning an instance of the generic delegate Action(Of T). Other generic delegates include Func(Of T) and Predicate(of T). (Refer to my article, Programming with Generic Delegates and Lambda Expressions for more on generic delegates.)

Now the benefit of generic programming where behaviors are passed around is that you dynamically--t runtime-change the behavior of a method simply by passing in a new behavior. For example, you could change UseDumper simply by passing in a different version of an Action(Of T) delegate. The following fragment demonstrates an alternate Lambda sub expression that can be used. This version uses LINQ and Array.ForEach to write the property information.

  Dim dumper2 = Sub(obj)
                      Dim dumdum = From info In obj.GetType().GetProperties()
                                   Select New With {.Name = info.Name, 
                                   .Value = info.GetValue(obj, Nothing)}
                      Array.ForEach(dumdum.ToArray(), 
                       Sub(input) Console.WriteLine("{0}: {1}", 
                      input.Name, input.Value))
      End Sub

Note that the Array.ForEach method also uses a Lambda expression as the second parameter.

Summary

Lambda expressions are not anomalous shorthand for lazy programmers. They support dynamic programming, extension methods, generic delegates, and LINQ. Most importantly they are kind of fun to write. Visual Basic 2010 supports Lambda function expressions and Lambda sub expressions. Just think of them as little time savers.



About the Author

Paul Kimmel

Paul Kimmel is the VB Today columnist for CodeGuru and has written several books on object-oriented programming and .NET. Check out his upcoming book Professional DevExpress ASP.NET Controls (from Wiley) now available on Amazon.com and fine bookstores everywhere. Look for his upcoming book Teach Yourself the ADO.NET Entity Framework in 24 Hours (from Sams). You may contact him for technology questions at pkimmel@softconcepts .com. Paul Kimmel is a Technical Evangelist for Developer Express, Inc, and you can ask him about Developer Express at paulk@devexpress.com and read his DX blog at http:// community.devexpress.com/blogs/paulk.

Comments

  • There are no comments yet. Be the first to comment!

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • In support of their business continuity and disaster recovery plans, many midsized companies endeavor to avoid putting all their eggs in one basket. Understanding the critical role of last-mile connectivity and always available Internet access for their enterprises, savvy firms utilize redundant connections from multiple service providers. Despite the good intentions, their Internet connectivity risk may still be in a single basket. That is because internet service providers (ISPs) and competitive local …

  • IBM Worklight is a mobile application development platform that lets you extend your business to mobile devices. It is designed to provide an open, comprehensive platform to build, run and manage HTML5, hybrid and native mobile apps.

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds