Architecture & DesignDynamic Programming with Lambda Expressions

Dynamic Programming with Lambda Expressions

Dynamic Programming with Lambda Expressions – Introduction


There are a lot of ways to write code. Sometimes we write
code as simply as possible, straight forward-perhaps inline
calculations and sometimes we add levels of indirection.
Indirection, or abstraction, makes code a bit more
challenging to understand, but abstraction can add
flexibility and a level of dynamism that can be very
powerful and useful.


This article shows you how to use Lambda expressions as
function arguments to support dynamic function behavior. If
you program like this for critical aspects of your
application then you will create a more flexible and
powerful solution.


Most of the Time


A lot of code is written in a direct way. Suppose you
have an application that needs to calculate sales tax. It is
reasonable to write the calculation directly. For example,
in Michigan the sales tax is currently 6%. To calculate
sales tax you could write:




Dim total as Double = value * (1 + .06)


If this calculation is written inline it will solve the
problem, but it does not represent a flexible or reusable
solution. The next evolutionary improvement is to define a
function that performs the calculation, and you could
provide an optional argument. For example, you could move
the calculation to a function and make the amount of tax
optional, providing the most common default value for the
tax amount. Listing 1 shows the code moved into a
function.

Listing 1: Reusable code with a regular function and
optional default value.


Function CalculateSalesTax(ByVal total As Double, _
Optional ByVal tax As Double = 0.06) As Double
Return total * (1 + tax)
End Function

All but beginning programmers eventually get to writing
code like the code shown in Listing 1 with the optional
argument usage being employed eventually.


The solution in listing 1 is practical and suffices for a
lot of scenarios. The only drawback is that it isn’t
flexible. You can pass in a total and a tax amount and the
calculation is always the same. And, as I said, for routine
solutions defining a well-named function is reusable and as
a plus self-commenting. Sometimes though you need to write a
solution that is even more flexible.


Some of the Time


Sometimes, especially if you are writing code that will
be used by others, you need to write your code more
flexibly. You can write your code to be more flexible by
adding function parameters. Function parameters mean that
part of the behavior will be passed in as a function. In
general, use this approach if you aren’t sure about all of
the scenarios that the function must support.


You can define function parameters a couple of ways. You
can define a delegate and define the function–parameter
type as an argument of the delegate type or you can use one
of the pre-existing generic delegates like
Func. To provide the function-parameter you can
add an existing second function and the
AddressOf operator or you pass a Lambda
Expression. Listing 2 demonstrates how to define a function-
parameter using the pre-defined Func generic
delegate and satisfy that argument with a Lambda
Expression.


Listing 2: A function with a function parameter satisfied
by a Lambda Expression.


Module Module1

Sub Main()
Dim total = CalculateSalesTax(100, 0.06, _
Function(sale, tax) sale * (1 + tax))
Console.WriteLine(total)
Console.ReadLine()
End Sub

Function CalculateSalesTax(ByVal total As Double, _
ByVal tax As Double, _
ByVal calculator As Func(Of Double, Double, Double)) _
As Double
Return calculator(total, tax)
End Function
End Module



CalculateSalesTax receives (all of it’s
behavior as the third argument. The third argument is
defined as Func(Of Double, Double, Double), a generic
delegate. Other generic delegates include Action(Of T) and
Predicate(Of T).


The calculator argument can be satisfied by any function
that has two double arguments and double return type. This
could be the address of a function, a Lambda Expression
assigned to a variable of the same type–Func(Of Double,
Double, Double)–or a literal Lambda Expression. In Listing
2 the calculator argument is satisfied by the Lambda
Expression




Function(sale, tax) sale * (1 + tax)


Lambda Expressions are just very condensed functions.
They use the Function keyword, parameter names with or
without the parameter types, and the statement that performs
the work. No End Function, no function name, and no return
keyword are required.


The opportunity with writing code like this is that the
consumer–the programmer using the code–can determine the
behavior to pass to the function–in the example
CalculateSalesTax. Assume for example that the sales tax is
a fixed rate unless the dollar amount exceeds $50,000. For
high priced items a luxury tax is imposed in some states.
Then, the consumer could incorporate the luxury tax
determinator in an alternate function. Listing 3
demonstrates an alternate implementation of the code
(incorporating an arbitrary value for the luxury tax).

Listing 3: An alternate implementation of the solution in
Listing 2 that adds additional functionality.


Module Module1

Sub Main()
Dim calculator = Function(sale, tax) IIf(sale > 25000, _
sale * (1 + tax + 0.02), sale * (1 + tax))

Dim total = CalculateSalesTax(100000, 0.06, calculator)
Console.WriteLine(total)
Console.ReadLine()
End Sub

Function CalculateSalesTax(ByVal total As Double, _
Optional ByVal tax As Double = 0.06) As Double
Return total * (1 + tax)
End Function

Function CalculateSalesTax(ByVal total As Double, ByVal tax As Double, _
ByVal calculator As Func(Of Double, Double, Double)) As Double
Return calculator(total, tax)
End Function
End Module

Notice that in the solution, a new Lambda Expression is
assigned to an anonymous variable. The new Lambda Expression
uses the IIf function to test whether or not the sale amount
exceeds 25,000; if it does an additional amount is added to
the tax amount representing a luxury tax.


Summary


The code in the solution uses a Lambda Expression and
function-parameters. The solution is both reusable and very
flexible because defining function-parameters means that
future consumers can provide part of the solution.


Having as many ways of providing solutions as possible
ensures that you are prepared for every day routine
programming and exceptional programming cases. The key to
great solutions is being aware of a wide variety of possible
solutions and picking the best one for a given context.


Biography


Paul Kimmel is the VB Today columnist for CodeGuru.com 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
[email protected]
.com
. Paul Kimmel is a Technical Evangelist for
Developer Express, Inc, and you can ask him about Developer
Express at [email protected]
and read his DX blog at http://
community.devexpress.com/blogs/paulk
.

Latest Posts

Related Stories