jueves, 25 de febrero de 2016

LINQ Recipe No. 1-2: How to Use the Func Delegate to Represent Functions

Contents

1. Introduction
2. Keywords
3. Problem
4. Solution
5. Discussion
6. Practice: Writing Functional Methods With Func Data Type
7. Conclusions
8. Literature & Links

1. Introduction

In this recipe the programmer will learn how to write functions using the Func<> delegate. As it will be shown, this delegate is the most versatile and useful mechanism to implement simple and compound functions. Also, the programmer will have the opportunity to grasp the theoretical and practical foundations of functional programming using the C# programming language.

2. Keywords

  • C#
  • Compound function
  • Data type
  • Delegate
  • Functional programming
  • Simple function

3. Problem

In the previous recipe we learned the purpose and the mathematical foundations for functional programming -LINQ Recipe No. 1-1: Introduction to LINQ Programming Model - Functional Programming-. We also developed some basic, but instructive, examples about simple and composite functions. Now what we need to do is represent that functions using the C#'s built-in programming elements.

4. Solution

The C# programming language offers to the programmer the Func delegate to build functional methods; using a very expressive syntax for complex functions.

5. Discussion

5.1 Delegates

The delegate data type is designed to specify an abstract method definition. For example if we define:

public delegate int ExecuteCalculation(int x, int y);

Then, any method which matches ExecuteCalculation's signature (parameters and return type) can be assigned to an instance of this delegate.

Given the method Add with this signature and return type 

public int Add(int x, int y)
{
return (x + y);
}

we then instantiate the ExecuteCalculation delegate 

ExecuteCalculation delegateExecuteCalculation;
delegateExCalculation = Add;

and finally, an intermediated call to the Add method is perfomed 

Console.WriteLine("Sum of 2 + 3 = {0}", delegateExecuteCalculation(2, 3));

Func built-in delegate is abstract because it receives any method signature which matches with its own signature:

public int Subtraction(int x, int y)
{
    return (x - y);
}

delegateExecuteCalculation = Subtraction;
Console.WriteLine("Sub of 2 - 3 = {0}", delegateExCalculation(2, 3));

5.2 Func C# class

The Func class represents built-in delegates to create functional methods. C# has up to 16 versions for this class. Each of them has a different number of generic parameters. This is because the programmer could be required to code a functional method with different set of parameters.

In the System namespace we can find all of the built-in Func delegates. They are 
  • Func(T, TResult)
  • Func(T1, T2, TResult)
  • Func(T1, T2, T3, TResult)
  • ...
  • Func(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, TResult)
Why do we need all of these Func versions? Because this avoid the explicit and manual declaration for delegates. For instance, the ExecuteCalculation delegate (declared in the previous section) can simply declared as:

Func<int, int, int, int> delegateExecuteCalculation;

and then assigned any of the previous sample methods:

delegateExecuteCalculation = Add;

But we can also write the delegate's implementation as follows:

Func<int, int, int, int> delegateExecuteCalculation = (x, y) => x + y;

6. Practice: Writing Functional Methods with Func Data Type

In the previous recipe -LINQ Recipe No. 1-1: Introduction to LINQ Programming Model - Functional Programming- we created the mathematical functions:

f(x) = x + 1
g(x) = x + 2

With the Func data type we simply define them as 

Func<int, int> f = x => x + 1;
Func<int, int> g = x => x + 2;

Therefore the mathematical compound function 

f(g(x))

is written in C# code as 

Funcint, int>, Func<int, int>, int, int> fog = (f1, g1, x) => f1.Invoke(g1.Invoke(x));

Unifying all of these examples, we write this complete C# program:



On line 10 we define the f mathematical function using Func<int, int>: input parameter as int, and int as return data type. This is also apply for the g mathematical function (line 11).


On the other hand, with line 14 the compound mathematical function f(g(x)) is specified with this code:
  • Func<int, int>: receives a Func type; which can be the f or g function. In this case f.
  • Func<int, int>: receives a Func type; which can be the f or g function. In this case g.
  • int: the input parameter for the inner function.
  • int: the output data type.
Compilation:

csc /t:exe FunctionalMethods.cs

Assembly execution:

.\FunctionalMethods.exe

Online execution (ideone.com): http://ideone.com/ztvRjz

Local execution:
FunctionalMethods.exe assembly execution
Illustration 1. FunctionalMethods.exe assembly execution.

7. Conclusions

In this recipe we have learned how to use built-in delegates to create functional methods with a very expressive syntax. Instead of writing our own delegates we can take advantage with the built-in ones: we must remember that there are up to 16 different versions of the Func type. With this in mind, we can make our code more expressive and manageable.

In the next recipe, we are going to understand types of functions.

8. Literature & Links

Mukherjee, S (2014). Thinking in LINQ Harnessing the Power of Functional Programming in .NET Applications. United States: Apress.
C# Func Type (2016, febrero 25). Retrieved from: http://www.dotnetperls.com/func
Using Delegates (C# Programming Guide) (2016, febrero 25). Retrieved from: https://msdn.microsoft.com/en-us/library/ms173172(v=vs.110).aspx


V

No hay comentarios:

Publicar un comentario

Envíe sus comentarios, dudas, sugerencias, críticas. Gracias.