Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

First Class Function Explained: Translate Complex Type to DataTable/JavaScript

0.00/5 (No votes)
12 Nov 2013 1  
Explanation about first class functions in .NET
A language is said to have first class functions if it supports passing functions as arguments to other functions and returning them as values from other functions. The values can be stored in data structures. This article explains why this can be advantageous and provides a real world example.

Introduction

Recently, I said to somebody in my team that .NET has achieved a lot in having first class functions. He didn't know what I was talking about. Then I explained a little on delegates and even SelectMany. He got a little bit lost, and wanted a real world example. So, I provided one.

A language is said to have first class functions if it supports passing functions as arguments to other functions and returning them as values from other functions. The values can be stored in data structures. The first part is simple:

private bool ValueReturnedFuncPassed(Func<string, bool> FuncArg, string someValue){
    return FuncArg(someValue);
}

We are passing a function as a parameter. We see a lot of this in current APIs, so it is becoming familiar.

A little less familiar is returning a function as a value. Look at the following:

private Func<string, bool> FuncReturned(){
    return(x => x.Length > 0);
}

The question is why and when should we use all this? Let’s look at several ways to accomplish the same:

//We make a very simple example here
//therefore provide either an empty string or a string with a certain length.
string myString = "some string";
        
bool bCheckLength;

bCheckLength = ValueReturned(myString);
bCheckLength = ValueReturnedFuncPassed((x => x.Length > 0), myString);
bCheckLength = FuncReturned()(myString);
bCheckLength = Required<string>()(myString);

// 1. Very well known way of coding
private bool ValueReturned(string someValue)
{
  return someValue.Length > 0;
}
//2. Passing a func delegate
private bool ValueReturnedFuncPassed(Func<string, bool> FuncArg, string someValue)
{
  return FuncArg(someValue);
}
//3. Returning a Func delegate
private Func<string, bool> FuncReturned()
{
  return(x => x.Length > 0);
}
//4. Returning a generic Func delegate 
private Func<T, bool> Required<T>()
{
  return (x => {
  if (x is String)
  {
    return (x as string).Length > 0;
  }
  throw new InvalidCastException();
});
}

The first example is the most limited. We need to pass a string and the check is fixed.

The second example is less limited, because we can pass in any check as long as it matches the Func delegate definition <string, bool>, which gives us a bit more flexibility.

The third example differs because the executing and the definition of method is separated. So we can use something like:

var funcToInvoke = FuncReturned();

Meaning we store a piece of code into a variable that can be executed later on.

The fourth example is the third made generic, and therefore called Required.

In earlier days, you probably used interfaces to accomplish this. If you don’t need all the compulsory characteristics of an interface, Func delegates can be an alternative.

Func delegates stored in variables (third and fourth case) can be added to a dictionary (key: string). One step further and you can put the methods to execute in a metadata (Required) or an XML file. I have seen a lot of code using Reflection to dynamically call methods. Delegates are far more efficient.

Let’s go another step further and just make a program by dynamically combining the dictionary stored delegates.

//Problems can arise because of unexpected state changes
bCheckLength = dictFuncStored["StringRequired"](myString);
myString = null;
bCheckLength = dictFuncStored["Required"](myString);

The last call fails, because we set myString to null. If you want to avoid this, you have to encapsulate the state in between calls.

//Solve the state problem by encapsulating
Func<string, Func<string, bool>, Func<string, bool>, bool> complex = (s, f1, f2) =>
{
    bool bret;
    bret= f1(s);
    if (bret ) return f2(s);
    return bret;
};
bCheckLength = complex(myString, dictFuncStored["StringRequired"], 
                       dictFuncStored["Required"]);

No need to say, this can become very complex, say we want to combine more than two methods while using differently typed func delegates. However, the changing state problem is a real problem in every program!

Let’s turn to our real world example in which I deal with this problem.

Real World Example. Translate a Complex Object to a DataTable or to JavaScript

Report writers often use the DataTable structure, a web page uses JavaScript. So can we make something in which to translate a complex object to both. Let’s do it with first class functions and deal with the state problem as well.

If we abstract a little, we can say that we have an object of some type and must translate that to an object of another type. If we want to deal with the state problem, we have to 'encapsulate' the state within this transition. We can do this by pairing the value and the state. Putting things together, we end up with:

public interface IPaired<out V, out S>
{
    V Val { get; }
    S State { get; }
}

public delegate IPaired<V, S> Paired<in I, out V, out S>(I i);

The translation is a two step process: in the case of the DataTable translation, we first have to create the DataTable with the right columns and then fill the DataTable with the objects. So we have an InitState and a FillState. This results in the following interface:

public interface IDataCast<T, S>
{
    IEnumerable<T> Source { get; }
    S InitState(IEnumerable<T> Source);
    S FillState(IEnumerable<T> source, S state);
}

The next problem is that InitState and FillState must be combined, without having the possibility to change the state in between and without ending up with complex constructs.

This is not simple, but luckily, there is LINQ. Here, we are only interested in one (small) aspect of LINQ, namely compiler support for SelectMany which makes it possible to write code like:

var ret = from p in persons
            from a in addresses
            etc.

which will be ported to a method with the following signature:

IEnumerable<TResult> SelectMany<TSource, TCollection, 
  TResult>(this IEnumerable<TSource> source, Func<TSource, IEnumerable<TCollection>> 
  collectionSelector, Func<TSource, TCollection, TResult> resultSelector)

And vice versa. If you have a method with the above signature, you can use the double from the class syntax so well known in LINQ. Keep in mind that the comparison with LINQ ends exactly here.

So we want to do something like:

public Paired ConvertDataStructure =
            from v in [Paired]
            from s in [Paired]
            select s;

[Paired] is a placeholder for a function that results in an IPaired delegate. The interesting part is that the two from clauses and the resulting select clause are all typed Paired! Which makes combining possible:

public Paired FillDatastructure =
            from v in [Paired] 
            from dt in ConvertDataStructure
            from s in [Paired] 
            select s;

The delegate Paired has two out parameters: value and state. I added a Pair class to wrap these two, so you can easily extract the state or the value.

If you arrive at this point, it is not that difficult to make a generic variant. So you can write:

var myDelegatesToConvert = DataCast<Person, DataTable>.FillDatastructure;
var myDelegatesToConvertJS = DataCast<Person, string>.FillDatastructure;

From which you easily can tell that the first is about translating from type Person to DataTable and the second from Person to string (JavaScript is string).

As explained above, we have only stored a piece of code into a variable that can be executed later on. The Run method is exactly doing this.

The rest of the code is 'normal' coding, which you can study on your own.

What is the advantage in doing this complex coding? If you look at the code, you could use the provider classes on their own, and you can add an XMLProvider or another one if you like. The 'lifting' of all this to the delegate variant is separated from the code that is doing the work. You don’t need to lift this. But look at the FillDatastructure, which combines the ConvertDatastructure. Say you have a lot of other filtering, selecting, transforming structures and you just can combine them in any combination, store them in variables, put them into a dictionary, and use these through metadata. And in all cases, you know that the state is not changed by something else, but yourself. Just think about it.

The subject of the article was explaining the first class function in a real world example. We explained functions passed as arguments, functions returned as values that can be stored in data structures (dictionary). We gave a real world example by lifting normal coding into a 'function context' which gives us another/new perspective. Maybe I can come back to this another time, because this article is only about explaining first class functions. Keep in mind that the code provided is only an example, it is not full proof, dealing with all scenarios.

History

  • 12th November, 2013: Initial version

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here