What is Old is New Again: Functional Programming
One of the greatest ideals of high level programming is the idea of code reuse. In the old days, this was only ever done using functions or subroutines, depending on the language. In later days, this was performed as object oriented design. Every language seems to accomplish these ideals in various ways to accomplish a similar goal.
Now, it seems the latest hot idea is Functional Programming. Wikipedia dates this concept back to 1950's with the introduction of LISP. Why do we, all of a sudden, now care about a 50+ year old concept?
What is Old is New Again
I remember my first few years learning programming. I spent lots of time on my Atari learning AtariBasic, typing in games and programs from books and magazines, and soaking in all the cool ideas I wanted to try. Basic was too slow, so, looking for a better way I picked up 6502 assembly and wrote some interesting stuff. But, my code looked like a steamy pile of fodder!
My observation was that clearly, as complexity of code increased my spaghetti code factor rose exponentially. Even if you realize this is happening to your project, you still hammer on the code just trying to get it done. Later down the road, you realize that the code is pretty much not very reusable because of all the assumptions made during development.
Functional Programming
The trick is to think stateless. Wikipedia defines functional programming as:
In computer science, functional programming is a programming paradigm that treats computation as the evaluation of mathematical functions and avoids state and mutable data. It emphasizes the application of functions, in contrast with the imperative programming style that emphasizes changes in state.
For example, many of the useful Unix commands are functional by nature. Each little command does a small task, which by itself is not ground breaking. However, you can chain each together to munge data into a usable result. For example, here you can merge two web log files together, filter lines containing "GET /", and browse the results a page at a time:
$ cat weblog1.log weblog2.log | grep "GET / " | less
Clearly, cat
doesn't know or care that its result is getting filtered, displayed, or simply ignored. less
doesn't care where it got its data from, it just reads STDIN and displays it in a browsable manner. Naturally, it almost looks like a math equation x = less( grep( cat(weblog1.log, weblog2.log), "GET /") )
.NET IEnumerable
I think the designers at Microsoft got one thing really right with .NET. They implemented a standard interface for iterating over any kind of data in sequence. This works for static arrays and many container objects. To get the most of it, you can think of it like Unix-style pipes. With minimal effort, you can take advantage of the deferred execution by implementing them like lazy lists.
Remember, we're avoiding the Imperative Programming style which adds unnecessary complexity to our code and reduces reusability. Each function maintains no state between calls and remains as generic and primative as possible for maximum reuse opportunity.
Here are some C# 2.0+ method signatures of some useful functions:
public static class Filter { public static IEnumerable<T> Grep<T>(IEnumerable<T> List, Predicate<T> FilterDelegate); public static IEnumerable<T> Splice<T>(IEnumerable<T> List, int OffsetIndex, int Count); public static IEnumerable<T> Skip<T>(IEnumerable<T> List, int Count); public static IEnumerable<T> Take<T>(IEnumerable<T> List, int Count); public static IEnumerable<T> Tail<T>(IEnumerable<T> List, int Count); public static IEnumerable<T> CompareTo<T>(IEnumerable<T> List, CompareOperator Operator, T Subject) where T : IComparable<T>; } public static class Convert { public static string Join(string SeparatorString, IEnumerable List); public static IEnumerable<T> Map<T>(IEnumerable<T> List, MapAction<T> MapDelegate); public static IEnumerable<TOut> Map<TIn, TOut>(IEnumerable<TIn> List, MapAction<TIn, TOut> MapDelegate) public static IEnumerable<T> Concat<T>(IEnumerable<T> List1, IEnumerable<T> List2); public static IEnumerable<TOut> TypeCast<TIn, TOut>(IEnumerable<TIn> List) where TOut : class; } public static class Compute { public static IEnumerable<int> Range(int Start, int End, int Step); public static IEnumerable<int> Counter(int Start, int Step); public static IEnumerable<int> Random(int Min, int Max); public static IEnumerable<Guid> RandomGuid(); public static int Count(IEnumerable List); public static int Sum(IEnumerable<int> List); public static int Average(IEnumerable<int> List); public static int Minimum(IEnumerable<int> List); public static int Maximum(IEnumerable<int> List); } public static class IO { public static IEnumerable<string> TextStreamReader(Stream Input); public static IEnumerable<string> TextFileReader(string Pathname); }
Let's try it out:
// Generate 10 random numbers List<int> NumberList = new List<int>( Filter.Take<int>( Compute.Random(0, 99), 10 ) ); // Dump numbers to Console Console.WriteLine( Convert.Join("\n", NumberList) );
There, no loops, no working variables, and no state management. The goal is that you, the developer, spend less time with overhead when working with data as a set. I admit, LINQ does a lot of this for you, but that feature has only been available since .NET 3.5.
Attachment | Size |
---|---|
Enumerable examples in C# (zip) | 6.13 KB |
- Login to post comments
About Shawn Poulson / Exploding Coder
Software developer and designer
I'm a software developer in the Philadelphia/Baltimore metro area that loves web technology and creating compelling and useful applications. This blog was created to showcase some of my ideas and share my passion and experiences with others in the same field. Read more...
Comments
Something practical
This is interesting, but how about something practical. I keep seeing every functional example of producing fibonacci sequences or some other numeric playfulness. I have yet to see someone apply the functional style to the typical OLTP style application that the many of us do on a daily basis. How could I delete a database entity and all of its relations in a single transaction in a functional way?
Practical use cases
This example just shows just one way to do set manipulation with IEnumerable. It's up to the implementer to make more concrete practical examples. Of the group, the Grep, Map, Splice, Take, and Tail will probably be the most useful as they are the most generalized. Those familiar with Perl will be right at home.
As a practical example, I've implemented these concepts in a project doing complex DateTime calculations. For example, I defined a class containing a start and end DateTimes, then created some classes that generate recurring events based on a pattern via IEnumerable, such as "every 2 hours". I can use the concepts in this example to make composite classes that perform calculations on one or more IEnumerable. This allows me to implement the equivalent of "every 2 hours, except on Sundays". YMMV.