Current area: HOME -> Blogs -> pheaven's Blog -> Read Post

Higher Order Programming Is Easy!

Posted on Tuesday, January 22, 2008 at 7:09 AM
Higher Order Programming is one of those things that to many people sounds weird, magical, mysterious or just too hard for them to be able to do. It's not. If you have ever passed a function or method as a parameter to another function or method, then you have done higher order programming. If you have ever used a function pointer in C or a delegate in C# or some kind of callback mechanism, then you have done higher order programming.

Define it!

We are all used to writing code that takes parameters. We do it whenever we write subroutines, functions or methods. Normally these parameters are data. In higher order programming, one or more of these parameters is code rather than data. That is, you can pass code, functions and/or methods around, just as you can pass data around. That's all there is to it.

Show me an example

Let's look at C#, because the syntax will not be too unusual to programmers in many languages. Suppose we have a List of scores for a test.
var Scores = new List<int>() { 2, 7, 9, 5, 6, 10, 8 };
We want to get all scores that were considered passes. Suppose the test is out of ten, and to pass you need to get more than half marks. We can write a method to determine whether a score is a pass and that returns a boolean (true or false value).
public bool Pass(int Score)
{
    return Score > 5;
}
Then we can use the FindAll method to find all scores that were considered passes.
var Passed = Scores.FindAll(Pass);
Notice what we have done here. We did not call the Pass method ourself. Instead, we passed the Pass method to the FindAll method as a parameter. Internally, it looped over the values in the list and called the Pass method on each of them, and put those that it returned true for into a new list and returned it.

You are probably now thinking, why go to all the trouble when I could have just written a loop? And it's true - you could have written a loop that did the test in an if statement and build a new list.
var Passed = new List<int>();
foreach (var Score in Scores)
    if (Score > 5)
        Passed.Add(Score);
However, step back and think about what we just achieved from a software engineering perspective. It is a well known principle that separation of concerns helps to reduce code complexity. Here we have separated the concerns of:
  • Testing each element of a list and building a new list of elements that passed the test
  • The test itself
Therefore, higher order programming is a tool that enables us to reduce our code complexity by separating concerns, and also increase code re-use along the way.

Code without a name

You might be thinking, "huh, I just wrote more code than I would have; I had to define a whole extra method!" You can also argue, quite reasonably, that we have actually made the program harder to understand now too, because you have to go and find the Pass method to fully understand the code.

While sometimes we may have complex conditions that we wish to re-use in many places in our program - in which case writing a separate function or method is the right thing to do - in this case it would be nice if we could take advantage of higher order programming without having to resort to writing a separate method.

Enter anonymous methods, or lambda expressions. These allow you to define a method (or function, depending on your language) without a name and inside another method. Let's re-write the previous example using a lambda expression.
var Passed = Scores.FindAll(Score => Score > 5);
The "=>" is the syntax for defining an anonymous method in C# 3.0. Anything to the left of it is a parameter that the method takes. In this case, it takes a single parameter named "Score". To the right of it is the body of the method, with an implicit "return" (that is, it will return the boolean result of testing whether its parameter Score is greater than 5).

You could read the "=>" quite nicely in this case as "where". That is, "find all scores where the score is greater than five".

Yes, you can return code too

Suppose that I want to work out how many scores got different grades. For example, Grade A was given for scores between 8 and 10, Grade B for given for between 5 and 7, and so forth. We could write:
var GradeA = Scores.FindAll(Score => Score >= 8 && Score <= 10);
var GradeB = Scores.FindAll(Score => Score >= 5 && Score <= 7);
However, it would be nice if we could make something that read more clearly, such as:
var GradeA = Scores.FindAll(Range(8,10));
var GradeB = Scores.FindAll(Range(5,7));
How could this work? Well, FindAll expects a method that takes an int and returns a bool. This type of method - that is, a method with that signature - has a name: Predicate. Therefore, the Range method needs to have a return type of Predicate (actually, Predicate<int>, which means that the parameter it takes is of type int).
public Predicate<int> Range(int LowerLimit, int UpperLimit)
{
}
And what do we write inside the Range method? Well, we return an anonymous function that takes a single parameter and tests if it is squeezed between the two values we supplied as parameters to the Range method.
public Predicate<int> Range(int LowerLimit, int UpperLimit)
{
    return x => x >= LowerLimit && x <= UpperLimit;
}
And that's it.

What languages support this?

Here's the stinger: not all languages support these kinds of programming techniques. C# started out with the ability to do higher order programming, but without anonymous methods. In C# 2.0 they introduced anonymous methods, but with a fairly cumbersome syntax. In C# 3.0, they introduced the nice "lambda" syntax that I have shown here. Essentially, the language designers have realized more and more the value of higher order programming and worked to make it as easy as they make object oriented programming. The C# of today is a truly multi-paradigm language.

Many of the dynamic languages provide good support for this, including Perl, Python and Ruby. C enables it through function pointers, though there's no anonymous method or lambda style syntax. Java, however, has so far chosen to stick to its object oriented roots rather than embracing the multi-paradigm approach. We'll leave arguing about whether that's a good or a bad thing for another time. And primarily functional languages, such as ML and Haskell, make extremely heavy use of higher order programming techniques.

Taking it further

The examples I've shown here are trivial, but they are enough to give you a taste of what higher order programming is about. Try writing some code like this yourself, or reading up on higher order programming in a language of your choice. And when you're trying to work out a good way to get better code reuse and reduce code complexity, keep it in mind as one of the tools in your toolbox, alongside the other paradigms (such as object oriented programming, procedural programming and generic programming) that you are probably already more familiar with.

Comments
x? - Posted on Wednesday, January 30, 2008 at 1:56 PM by ngs
Where is x coming from in the Predicate function?

return x => x >= LowerLimit && x <= UpperLimit; ??
still not understanding... - Posted on Wednesday, January 30, 2008 at 2:26 PM by ngs
So I pulled a stupid and asked a question before looking up a definition for "predicate" with is basically a collection?

Still. I don't see how or when your defining x unless x is a self constructing object? And your returning a collection, not a function unless I'm totally confused now. Let me reiterate: I am totally confused. The understanding I had before you threw all that out concerning C# is that you pass a function instead of a value or a pointer. Ok, sure... I guess. To me it kind of seems like it would be a function pointer in C++. But your working around actually passing a function and just calling a function that returns a collection of integer values that the next function in the progression will interpret as a collection and iterate through to calculate another collection and so on until one value or a result is determined.

Sorry, I'm a pretty low level programmer by nature and this doesn't seem like anything out of the ordinary. Again...unless I'm missing something.
... - Posted on Wednesday, January 30, 2008 at 2:30 PM by ngs
I still don't see where x is defined as a collection though.

Sorry for the comment spam.
Predicates and parameters - Posted on Thursday, January 31, 2008 at 1:58 AM by pheaven
Hi,

Thanks for the question. A Predicate is a function that returns a boolean result (either true or false). So the type Predicate<T> refers to a type of function that takes some parameter of type T (basically, any type that we choose), does some test on it and returns true or false. Pretty much all of the functions I've been writing in this example are predicates. So:

Score => Score > 5

Declares a predicate function that takes a parameter of type int and tests if it's greater than 5. Doing "Score > 5" gives us a boolean result - either true or false. So actually that is a Predicate<int>, though the compiler works this out for us and we don't have to write it anywhere - unless we're writing a function generator, which is why I had to bring it up. If you're familiar with generics, all that's going on here is that we have a generic delegate.

On the "where does x come from" bit. You should read the left hand side of the => operator as a parameter list. So actually when we write:

x => ...

Then we are declaring that x is a parameter for the anonymous method defined to the right hand side of the arrow. That is, we declare x here - it didn't exist before this point. Further, x only exists inside the definition to the right hand side of the => - that is it's scope. So x doesn't come from anywhere - it is just a name that we chose. All of these are equivalent:

x => x > 5
y => y > 5
monkey => monkey > 5

Just in the same way that all of these are if we were to write it as a normal, non-anonymous method:

public bool Test(int x) { return x > 5; }
public bool Test(int y) { return y > 5; }
public bool Test(int monkey) { return monkey > 5; }

You choose the parameter name and you use it inside the method, but changing its name won't change the behavior of the method (unless you had a field with the same name it would maybe do so of course, but that aside...)

Hope this helps?

Jonathan
sort of... - Posted on Thursday, January 31, 2008 at 7:48 AM by ngs
So basically, instead of the common programming data flow of passing data down the function tree, your passing a generic function. (which IMO would be more confusing)

What I still have an issue with, however, is what datatype is x? Is it an int or a boolean? How I read it your returning x, but your defying common standards by passing x on the left instead of the right, so your not actually returning x, but your passing x (whatever that is) to an anonymous function block (without blocks? How do you know it ends?) and returning a boolean? Someone that is reading this from a programming background would probably do as I just did and wonder why you need the Predicate generic if your just passing a boolean back. And since we are on the topic, is boolean the only type you can return in this methodology?

ie:
boolean private Range(int min, int max, int val) {
return (val >= min && val <= max);
}
where val is passed using => in your method, but what does the FindAll function look like to pass this value?

I understand it as far as passing the function as a delegate. That makes sense to me, but I still think I would have coded Range to return a collection instead of a boolean and FindAll would loop through the collection and compare it to the dataset in the Scores object.

Anyway, Sorry to derail the topic. It feels backwards to me, but to each his own I guess. Different people think in different ways.
Type inference - Posted on Friday, February 01, 2008 at 2:50 AM by pheaven
Hi,

Underlying this approach is the notion that code and data are really one and the same. Once you make that assumption, passing code around (well, actually a reference to some code, just like a function pointer in C/C++) is not so surprising.

Taking the line that you asked about, let me try and take it apart.
public Predicate<int> Range(int LowerLimit, int UpperLimit)
{
    return x => x >= LowerLimit && x <= UpperLimit;
}

Here, we declare that the return type of the method is Predicate<int>. If we look at how that is defined in the .Net class library, it is something like:
public delegate bool Predicate<T>(T Item);

That is, it's a method that takes an item of type T and as a parameter (T being supplied as a type parameter when we use the delegate) and returns a boolean.

Now, inside the method. The compiler sees:

return

OK, so we are about to return something of type Predicate<int>. So now it knows that whatever is returned is going to be a method that takes a parameter of type int and returns a bool (that is, we're not going to return a bool, we're going to return a chunk of code - a method or anonymous method).

Then we have:

x =>

This declares an anonymous method with a single parameter x. By knowing that we are expecting to return a method that takes a parameter of type int, the compiler can then assume that x is of type int. So it generates a new anonymous method with a single parameter of type int and with the body:

x >= LowerLimit && x <= UpperLimit

Though in fact, it has to insert a "return" for us. In fact, we could have written:

return x => { return x >= LowerLimit && x <= UpperLimit; };

Which is equivalent, but longer.

As for the FindAll method on the List<T> class, it takes a parameter of type Predicate<T> - that is, a method that takes a parameter of type T and returns a boolean. The compiler knows T this time because it knows the type of the list. And having been passed this, it can call it on every item in the list, and build a new list when whatever method is passed returns true.

Hope this maybe makes a bit more sense,

Jonathan
dsf - Posted on Monday, May 12, 2008 at 4:20 PM by sdf
http://vredit.wikidot.com/free-credit-report
http://vredit.wikidot.com/free-annual-credit-report
http://vredit.wikidot.com/free-credit-report-com
http://vredit.wikidot.com/free-online-credit-report
http://vredit.wikidot.com/my-free-credit-report
http://vredit.wikidot.com/free-credit-report-on-line
http://vredit.wikidot.com/free-credit-report-and-score
http://vredit.wikidot.com/free-credit-report-government
http://vredit.wikidot.com/free-credit-score-report
http://vredit.wikidot.com/free-anual-credit-report
http://vredit.wikidot.com/get-a-free-credit-report
http://vredit.wikidot.com/www-free-credit-report-com
http://vredit.wikidot.com/get-free-credit-report
http://vredit.wikidot.com/free-yearly-credit-report
http://vredit.wikidot.com/free-credit-reports
http://vredit.wikidot.com/credit-report-for-free
http://vredit.wikidot.com/experian-free-credit-report
http://vredit.wikidot.com/free-annual-credit-report-com
http://vredit.wikidot.com/free-credit-report-no-credit-card
http://vredit.wikidot.com/free-credit-report-gov
http://vredit.wikidot.com/free-copy-of-credit-report
http://vredit.wikidot.com/free-instant-credit-report
http://vredit.wikidot.com/free-credit-report-no-credit-card-required
http://vredit.wikidot.com/totally-free-credit-report
http://vredit.wikidot.com/free-annual-credit-reports
http://vredit.wikidot.com/free-credit-reports-online
http://vredit.wikidot.com/how-to-get-a-free-credit-report
http://vredit.wikidot.com/my-free-credit-report-com
http://vredit.wikidot.com/your-free-credit-report


Sponsored links

Build IT Knowledge with Current & Trusted Content
Helps Employees Develop & Hone New Technical Programming Skills. Sign Up & Get Full Access.
Check Out IT Certification Preparation Materials
Sign Up With SkillSoft & Get Access to Training Materials for Over 50 Professional Certifications.
Six Sigma Certification
100% Online-Six Sigma Certificate from Villanova - Find Out More Now.
Virtual File System SDK
Create your own file systems in Windows and .NET applications
PureCM Software Configuration Management
Version control and integrated issue tracking - powerful and easy to use. Get your FREE trial now!


Newsletter | Submit Content | About | Advertising | Awards | Contact Us | Link to us |
© 1996-2008 Community Networks Ltd All rights reserved. Reproduction in whole or in part, in any form or medium without express written permission is prohibited. Violators of this policy may be subject to legal action. Please read Terms Of Use and Privacy Statement for more information. Development by Synchron Data - .NET development.