Sunday, October 01, 2006

Musings on TMP and FP

If you've been reading this blog lately you'll see that I've been trying to understand how the Functional Programming Libraries have been implemented by trying to implement one myself. It's more of an excercise for my understanding, more than anything else. It will really be interesting if C++ will get lambda support in the next standard but that's a "wait-and-see" thing. Right now though, I'm trying to understand how you would go about it if you were using the existing language features (like templates, operator overloading, among other things).

Template Metaprogramming (TMP)

I would like to get really deep into the TMP way of doing things first by understanding template specialization and its intricacies. For one, I have observed that it's really tideous if you're out to implement your own TMP algorithms without existing library support like Boost.MPL -- I tried implementing a "max<N,M>" template metafunction, and I quickly saw how it would be an explosion of specializations even just for the first 100 numbers (of course, without library help, what would I expect).

Another observable advantage of doing TMP is the ability to specify behavior during compile time. For instance, your harmless type-deducing operator+ implementation might return an instance of a type which depending on the types of the arguments to the call to operator+, either implement the operator() which takes one argument or two arguments (or none!). There are template patterns such as CRTP (Curiously Recurring Template Pattern) and PBCP (Parametric Base Class Pattern) which are very interesting indeed, and allow for very good and extensible library design.

There's another compelling reason why TMP is something worth learning (for me at least): it allows for writing generic code which can easily be reused in many different contexts without significant and prohibitive performance degradation. The techniques for template metaprogramming also allow for policy-driven components not only in terms of types, but also for behavior.

Functional Programming (FP)

So what has TMP have to do with FP? For one, templates are evaluated recursively by an in-built interpreter (the C++ compiler) in a functional manner -- templates may either take in types or templates and then return concrete types which may then be used as template parameters, which in turn return types which may then be used as template parameters... And in the end, the code produced is valid C++ code.

Let's backtrack a bit here... FP is about using functions that deal with values or functions that return values or functions which in turn can be used as arguments to functions that deal with values or functions that return values or functions... And in the end, the function can be called and used. Do you see a parallelism between FP and TMP? If not yet, you can think about it this way: doing TMP is essentially doing FP albeit in compile time -- types and (static constant) values are immutable, there are no side effects because there are no variables, and the output is either a value (type) or a function (template).

So if TMP is more or less FP, why not bring FP to the user? The obvious answer would be language support. The next would be a matter of convention: most people get introduced to C++ and are told that it's an object oriented language. True enough, but C++ also allows for (among other things) imperative programming, generic programming, and recently functional programming.

So what's the missing link between FP and TMP? A library that's usable enough for everyday programming tasks, and extensible enough for general programming requirements. Some have come close, which I have cited in my post regarding Functional Programming but I would like to see something made part of the standard library.

Synergy

Now with the modern C++ concepts and idioms/practices, it should be feasible to make a fully functional "functional programming library for C++". Techniques for template metaprogramming now allow for generating efficient runtime code, recent improvements in the C++ compiler optimization techniques now make the efficient runtime code from TMP more efficient, and recently a proposal for Lambda functions has been proposed for the next C++ language standard.

All this for the intellectual discourse of a student in C++ programming and learning more about library design. I am excited to think that the concepts I can learn and apply seem endless in this pursuit to understand how Functional Programming in C++ can be enabled, as well as writing truly generic libraries for the community.

Now I go back to hacking.

9 comments:

Jesse said...

At SD West 2006, David Abrahms made the
point that template metaprogramming was a
kind of functional programming. Of course, he also does lots of work with the Boost MPL, so it seems natural to look there.

I haven't gotten deeply into it yet, but am presently reading Abrahm's book. What are in your view some of the shortcomings of Boost::MPL?

By the way, I am really enjoying your quality modern C++ blog!

Dean Michael said...

Hi Jesse!

I haven't read Dave's book yet (which reminds me, I should get myself a copy of that soon...) so I can't comment on what he has said there. About the shortcomings of Boost::MPL, I admit I'm just still starting to check into what the implementation brings, and how I can help fill the gaps (if there are any that I can see).

For the matter, I think the growing use of Boost.MPL will allow much of the issues to get ironed out (or at least, talked about) pretty quickly.

There are two things though at the top of my head: insanely long compile times and insane error messages. Maybe these just need getting used to, but I believe the recent use of the template features will really implement the compiler implementations that will be coming out in the future.

Aside from those two, I pretty much think Boost.MPL needs a lot more love from a lot more people. ;)

BTW, thanks for dropping a line. I certainly hope you'll come again. :)

Jesse said...

Hi, Dean! :>

Thanks for the great reply!

Unfortunately, my understanding is that the nature of templates presently prevents error messages from being improved much.

I believe that the issue is that the compiler only sees the expanded code and has no way of knowing how it was generated, so all it can show you is the result of the template computations.

There's a utility called "gfilt" that can kinda help pretty-print g++ results.

I have gotten > 30kb error messages when working with the Boost::Spirit library. (A VERY cool library, by the way, really worth a look!)

My understanding is that several features in the new language standard, C++0x, are there specifically to address those woes. Another positive thing I learned at SD West 2006 was that the top folks know about the nuisiance and difficulties-- they don't like them either. That's kind of reassuring.

It's all definitely very interesting, though! I am very much looking forward to playing with MPL some more!

I know what you mean about everything needing more love-- many people I know got very turned-off by C++ in the 1990s and haven't looked again at the amazing things that are being done now that we have compilers that work a bit better. ;>

Dean Michael said...

I should definitely look into gfilt, though I pretty much go by the "look at the the first error and hunt that down approach" when tracking down compile errors. Though more than 30kb worth of compile errors will definitely need a lot of pretty printing help. :D

I use Spirit too, and I personally know Joel de Guzman -- we've been having drinks for a while now here in the Philippines, and he's a very very cool guy too. I'm very much more interested in helping make Phoenix 2.0 a more mainstream library -- and making functional C++ a mainstream programming paradigm.

I so very much like the Variadic Templates and Concepts extensions. I would love to see Lambda get in, but that's something that just might have to wait.

And modern C++ definitely deserves a second look. I think frameworks like ACE and the castrated embedded C++ compilers/frameworks have scared people away or backed them down into a corner.

If I can just convince the teachers in college here in the Philippines to give C++ a second look, that might make a difference in the next generation. That way more people can give more love to the C++ libraries that deserve the attention.

:)

Jesse said...

Totally agree!

I just read some past blog posts and see that you certainly are already familiar with Spirit. Oops, bad me. :D

I also hope that good lambda support is on the way. We'll see!

I think that you're right: one of the largest problems is that since there's no central "C++ community", people don't know about the cool libraries that are out there to make life easier.

The right libraries make /all/ the difference!

Anyway, back to work for me-- but "hi" from Oregon/US!

Dean Michael said...

The right libraries do make all the difference. :)

Thanks for the comments!

<< misses the California Weather though. :D

Anonymous said...

Ack. I must have been asleep the other day. I was thinking of this tool, STLfilt, not gfilt: http://www.bdsoft.com/tools/stlfilt.html
-J.

Dean Michael said...

Looks like a nice tool indeed, however it doesn't support the more modern GCC (3.4 and 4.x).

Worth a look still anyway. :) Thanks for the link!

Jesse said...

I am using it with g++ 4.1.0, it seems to do all right. Anyway, great blog! :> -J.