Functional Programming in C# 3.0 using Lambda Expression - Part 2

This article explains how to use C# 3.0 lambda expression & LINQ for functional programming

Introduction

In Part 1 of this article, we have seen that the two of eight functional factors are satisfied in C# 3.0 using generic and lambda expression. In this article, let us see how does C# 3.0 satisfy remaining factors:

Anonymous function name(proved)

Type inference(proved)

Parameterized types

High order functions

Immutable data structure

Recursion

Currying

Lazy evalution

Generic Lambda Expression - contd.

Part 1 of this article, we have seen Func and Action provide very lighter syntax which avoid the need to declare a Delegate type for a lambda expression. Code 1 shows the usage of Func.

Delegate type declaration is not necessary when using generic lambda expression. In Code 1, you can see that Func<int, int> Square provides parameterized type for the expression x => x * x;. This enables the C# compiler to infer the type detail of x. Note that delegate type declaration also provides type details to C# compiler, however this syntax improves developer productivity. This satisfies factor #3 Parameterized types. Let us see one more example (Code 2) using generic lambda expression which satisfies next two functional factors.

ForEach in .NET 3.5 generic collection requires Action<T> type, here Action<int>. The line primes.ForEach(x => primeCubes.Add(x * x * x)); shows how C# 3.0 allows you to easily pass a method as an argument to a method. Here x => primeCubes.Add(x * x * x) function is passed as argument. This proves that C# 3.0 satisfies functional factor #4 high order function. In this example, you can also see the immutability nature of .NET 2.0's collection types so that I have used one more List<int> type primeCubes. This behaviour proves the functional factor #5 immutability data structure.

In this example, you can see that the method XPowerN requires n and x of type int and float respectively as arguments and it calculates xn by calling itself recursively. This proves functional factor #6 recursion.

Note: In Code 3, you cannot declare the method XPowerN like the following:

There are other ways to resolve this issue, however, I am comfortable with the approach shown in Code 3.

In code 3, Square and Cube methds use XPowerN method with n value as 2 and 3 respectively. The return value of these methods are the return value of XPowerN. This proves functional factor #7 currying.

Expression Tree

In addition to lambda expression, .NET 3.5 introduces expression tree which is a data structure generally used to represent an expression. In the tree, nodes contain either operands and operators. For example, the expression 3 + (5 + 9) * 2 can be represented as expression tree as shown in the following figure.

Let us see an example (Code 4) to calculate volume of a cylinder (v = πr2h, where r is radius and h is height) using expression tree.

In code 4, the only difference between lambda and expression tree is Expression<T>. The compiler emits respective expression types (operators and operands) in IL as shown in code 5. In code 4, the line XTCylinderVolume.Compile()(3, 9); tells the compiler that compile the expression but delay the evaluaion till invoked. The Compile method actually compiles the code represented by the expression tree into an executable delegate. This executable code is equivalent to the executable code that would have been generated had the lambda expression been assigned to a delegate type originally. This is called as lazy evaluation means that the expression will be evaluated only at the invocation, that is only at (3,9). Lazy evaluation is actually the functional factor #8.

Based on the above, we can strongly say C# 3.0 is a functional programming language too. Moreover, LINQ in .NET 3.5 really uses the above to enable the developers to write code which use both procedural and functional whereever suitable. Lazy evaluation is one of the major advantage of LINQ. The following figure shows the building blocks of LINQ

In the above figure, you can see that lambda expression and expression tree are two fundamental building block of LINQ. Code 6 shows the usage of LINQ with these features:

Comments and Discussions

Thank you for taking the time to walk through functional programming theory, logic and application. I needed to update my knowledge on the topic and it took me less than an hour because of your articles.