C# Functional style - Part 2
07/21/2018
2 minutes
In the previous post, I have looked how I could compose methods together:
int RequestHandler(int x) => LogOutput(Add1(LogInput(x)));
As it is a bit difficult to read (inside out), I would like to see alternative solutions to compose them together while achieving the same results.
For the following methods, it is needed that each method has one input parameter and one result returned. In the following posts, I will use the partial application of arguments and currying to achieve this.
One way to compose things together (and not pipe) is to create a helper extension method defined as:
public static Func<TIn, TOut> Compose<TIn, T, TOut>(this Func<TIn, T> current, Func<T, TOut> next) => x => next(current(x));
It takes two methods with 1 input parameter, where the result type of the first method is the same as the input type of the second method. It composes the two methods together by invoking the second method on the first method's result.
Now we can compose the methods (LogInput, Add1, LogOutput) from the previous post as follows:
Func<int, int> GetRequestHandler() => ((Func<int, int>)LogInput).Compose(Add1).Compose(LogOutput);
and optionally we can add a RequestHandler method, which invoked the composed Func on x.
int RequestHandler(int x) => GetRequestHandler()(x);
Using this straight in a .Select() extension method for IEnumerable , it would compose the methods together on each item of enumerable, which has a bad performance. So instead we will need to compose the methods once, store the result in a local variable and use that in the Select():
IEnumerable<int> input = Enumerable.Range(0, 3); var requestHander = GetRequestHandler(); input.Select(requestHander).ToList();
Looking at this solution, it might be a little more readable to compose the methods together, but I still don't like the way we need to cast the 'LogInput' method for the composition:
((Func<int, int>)LogInput)
So in the next post will look into further options, by taking it to a higher level and generating Func-s at runtime for the compositions.