Functional Programming in Simple Terms: Explained

In the next article, we would look at the characteristics of Functional Programming. This article assumes the user has basic knowledge of writing simple C# programs and understands delegates.

Functional Programming (FP) in simple words is a "Declarative Programming". That means FP does not deal with how to do (lines of code for achieving some functionality) but speaks about what to do. Microsoft introduced FP support with the release of .NET 3.5. LINQ and Lambda expression are one of the implementations of FP.

Let us say we have a customers object and we want to determine a customer based on the city "London", in normal programming. To accomplish that we need to loop through each object and check if the customer.city == "London". But the same thing can be accomplished using the Lambda Expression without writing more lines of code (in fact a one line statement) as below:

//Class Customer
 public class Customers
 {
        public int CustomerId { get; set; }
        public string CustomerName { get; set; }
        public string City { get; set; }
 }
 //creating list of customers
  List<Customers> customers =new List<Customers>
  {
   new Customers(){CustomerId = 1,City = "Delhi",CustomerName = "Praveen"},
   new Customers(){CustomerId = 1,City = "London",CustomerName = "Raheem"},
   new Customers(){CustomerId = 1,City = "Malvern",CustomerName = "Pradeep"}
  }; 
 //Lambda expression to filter customers based on city
 var findCustomerAtLondon = customers.Where(c => c.City == "London");

All of us know how to write a delegate. Simply a delegate is a strongly typed function pointer which refers to a method that has the same signature as the delegate.

A simple example of a delegate is as follows:

    //a delegate which takes two int parameters a and b
    //return type is a integer
    delegate int MyDelegate(int a, int b);
    public class Program
    {
        /// <summary>
        /// Method to add two numbers
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <returns>integer</returns>
        public static int Sum(int a, int b)
        {
            return a + b;
        }
        /// <summary>
        /// Main Method
        /// </summary>
        /// <param name="args"></param>
        public static void Main(string[] args)
        {
            //creating instance of a delegat MyDelegate
            //this instance refers to the method Sum
            //both the signatures match
            MyDelegate myDelegate = Sum; 
            int @delegate = myDelegate(5, 6); 
            Console.WriteLine(@delegate);
            Console.Read();
        }

1.gif

Figure 1:
Sum of two numbers

So you can use strongly type delegates for referring to the methods if the signatures match. C# has another way of doing this; by using generic functional types (Functional Programming). It is represented as Func<T, Result>.

We can replace the above delegate instance with the following code:

Func
<int, int, int> f = Sum; 
int @delegate = f(5, 6);

Syntax of Func in detail

A function type is represented as Func<T1, T2…TN, Output> where T1...TN can be of any type that is input to the function and Output is the return type of the function. Wherever we use delegates, those can be replaced with function types.

We can also write the above code as the following using a lambda expression:

Func
<int, int, int> f = (a, b) => a + b;
int @delegate = f(5, 6);

So, you should be able to refer to a method and its type can be used as a variable and it can return a type too.

Other than Func, we have two more generic function types. They are Action and Predicate.

An Action simply is a function type which returns nothing i.e. void.

A Predicate is a function type which returns Boolean.

So you can represent an Action as:

Action<T1...TN>

Equivalent to Func<T1...TN, Void>. Do not try to create with this syntax as the compiler will give an error as void is not a return type.

Predicate can be represented as below

Predicate<T>

Equivalent to Func<T, bool>. You can try this and it works.

Action and Predicate in detail

Let us try to understand how we can use Action by modifying our previous code

Declare a class variable with Action type

Here the Action type takes an integer value and performs some functionality based on which function it is referring to.

private
static readonly Action<int> write = Console.WriteLine;

We have defined a variable of type Action and it is pointing to the method WriteLine of the Console class. Since, WriteLine does not return any value we can make Action to refer to the method.

Now you simply replace the code for Console.WriteLine with write variable.

write(@delegate);
Console.Read();

Now let us see how we can use the Predicate.

string
name = "Ravi";
Action<bool> print = Console.WriteLine;
Predicate<string> myPredicate = (a) => (a.equals("Raju"));
bool predicate = myPredicate(name);
print(predicate);

Here I have declared a string variable and then created another Action type which takes a Boolean value and prints it using Console.writeLine method. I have declared a Predicate Type and this refers to the lambda expression that checks if the value is equal to "Raju". This would return a false value.

Output of Predicate and Func using Action is as below

2.gif

I am providing some more examples of Func, Action and Predicate for better understanding

We have the following functions available. Now try to identify what function type is to be used for each method.

static string SayHello(string userName)
{
       return string.Format("{0} says Hello to you", userName);

static void PrintMyName(string myName)
{
      Console.WriteLine("My name is {0}",myName);
}
static bool CheckIfTwoStringsAreEqual(string a, string b)
{
      return (a.Equals(b));
}
static bool IsGreaterThan5(int a)
{
       return a > 5;
}

The first method takes a sting parameter and returns a string type. So, according to what we understood it must be referred by Func type.

Func<string, string> hello = SayHello;
string s = hello("Venu");

The second method takes a string parameter and returns void and so, it must be referred by Action Type.

Action<string> print = PrintMyName;
print("Venu");

The third method takes two string parameters and return Boolean type. So, it can be referred by Func type.

Func<string, string,bool> check = CheckIfTwoStringsAreEqual;
bool b = check("abc", "abc");

The fourth method takes only one int parameter and returns bool and so we can use Predicate for this.

Predicate<int> predicate = IsGreaterThan5;
bool predicate1 = predicate(10);

It can be replaced by Func type.

Func<int, bool> func = IsGreaterThan5;
bool func1 = func(5);

Important points to note (Some extra information)

A Func type or Action can take only up to 4 parameters and Predicate can always takes only one parameter. If you try to add extra parameters other than they support compiler gives you an error message. According to best practices, any delegate should refer to a method which does not take more than 4 parameters. If any method is taking more than 4, you might have to refactor it.

The following are according to .NET 3.5.

4.gif

If you are using .NET 4, then you will see the supported number of parameters as below

Predicate still takes one parameter only.

Action takes 16 parameters.

public delegate void Action<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8, in T9, in T10, in T11, in T12, in T13, in T14, in T15, in T16>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15, T16 arg16); 

public delegate bool Predicate<in T>(T obj);

Func takes 16 parameters

delegate TResult Func<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8, in T9, in T10, in T11, in T12, in T13, in T14, in T15, in T16, out TResult>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15, T16 arg16);

Also observe that if you click on "go to declaration", it shows that Action is a delegate. So, internally the generic function types are also delegates.

Conclusion

The main intention of the article is to getting familiar with 3 generic function types: Func, Action and Predicate. In the next article we will try to understand the concept of Functional Programming in more detail.

Hope you liked this article.

Up Next
    Ebook Download
    View all
    Learn
    View all