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.

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read