Frequently Asked Questions

about the FC++ library



[0] Why is FC++ necessary when we have function pointers?

There are two key reasons and one minor reason why FC++ is better than using function pointers for implementing higher-order functions in C++. First, function pointers are monomorphic--you cannot create a pointer to a polymorphic (template) function. (You can create a pointer to one of its monomorphic instances, but you lose the polymorphic power in doing so.) FC++ can pass polymorphic functions as parameters. Second, function pointers can only point to functions that explicitly appear in the code. For instance, one cannot create a function pointer to a function created by specializing another function. Finally, function pointers add a layer of run-time indirection that can slow down your program by hindering optimizations like inlining. FC++ uses member function templates so even higher-order instantiations can be inlined. 


[1] How does FC++ compare to the "functional" part of the C++ Standard Library?

"Functoids" in FC++ are similar to "Adaptable N-ary Functions" in the STL, in that they use nested typedefs to encode argument and result types to enable composition of higher-order functions. The key difference is that the STL's "Adaptables" are all monomorphic. For instance, you can pass plus<int>() as an argument to many STL functions, but you must fix the argument type (int in this example). With FC++, you can just pass Plus() to a polymorphic higher-order function, and have the argument types be deduced later/elsewhere. 


[2] What compiler can I use for FC++?

Any conformant C++ compiler should work; see the compiler page for details.


[3] Will FC++ make my programs slower?

Probably not. In principle, if you need to use a functional idiom in your program, FC++ is one of the most efficient ways to do it. Sections 4 and 5 of the paper Functional Programming with the FC++ Library contain an analysis of the run-time performance of the library.


[4] What would functional programming in C++ be good for?

A lot of programming patterns could be written more concisely with FC++. An example would be lazy data structures (where the members of the structure are not evaluated until needed). Another example would be type-safe callbacks: the Observer design pattern essentially implements callbacks in an object-oriented way, but with functional idioms the same can be done more cleanly. Finally, function specialization is very straightforward so new functions can be created from fixing some arguments of old ones. The paper FC++: Functional Tools for OO Tasks describes how FC++ can be used in the implementation of design patterns.


[5] What does take (5, map (odd, enumFrom(1))) mean?

The functions named above are all part of Haskell's standard library (called the Standard Prelude). Haskell is a modern pure functional programming language, and much of the functionality of FC++ mimics Haskell exactly. This is meant to make FC++ more accessible to the "functional programming crowd" who may be less familiar with C++.

In this example, enumFrom(1) creates an infinite list of integers (1, 2, 3, ...), odd is a function which returns true if its argument is odd, map works like MAPCAR in LISP by applying its argument to each element of a list, and take selects the first N elements of a list. As a result, the expression above resolves to the list (true, false, true, false, true).

For documentation of the meaning of the FC++ functoids defined in prelude.h, you should check out the documentation of the corresponding Haskell functions (see section "A.1" that starts about half way down the page).


[6] Haven't other people done functional programming in C++ before? How is FC++ different?

FC++ is the first library to enable polymorphic higher-order functions that have polymorphic arguments. In the past, if one wanted to express polymorphic functions in C++, these couldn't be used as arguments to other functions. This may seem like a detail, but it is particularly useful in C++ because of the limited type inference capabilities of the language. For instance, consider the standard FC++ example:
  take(5, map(odd, enumFrom(1))) .
Without the ability to have polymorphic functions that take other polymorphic functions as arguments, odd would have to be monomorphic (i.e., it would lose in generality). With FC++ we have a fully general definition of odd, pass it to map and let map determine its required type later. An even better example is:
  compose(tail, tail).
The above composition is a polymorphic function (assuming that tail is also polymorphic). No C++ library before FC++ supported something similar.

FC++ also offers several expressiveness and performance enhancements over older libraries for functional programming in C++. It defines a subtyping policy for functions (so you can substitute a more general function where a specific one is expected), it offers efficient memory management, it defines a wealth of operators commonly found in functional languages, it provides automatic currying of functoids, it provides infix function syntax, it comes with an implementation of a lazy list data structure, and it provides interface functions from STL function objects, C++ function pointers, etc. to FC++ functoids.


[7] Does FC++ make C++ a functional programming language?

That depends on your definition of "functional programming language". The moniker "functional programming" is a wide umbrella (it encompasses languages as different as LISP and Haskell, for example). Nevertheless, there are some features that seem common among functional programming languages. Here is one possible enumeration of features which functional languages typically support a majority of, as well as details of how well FC++ supports them:

Features:

  1. referential transparency (no assignment of variables, no side-effects)
  2. higher-order functions (functions passed/returned as values)
  3. lambda (ability to create anonymous functions)
  4. currying (partial application)
  5. polymorphism (parametric)
  6. automatic memory management
FC++ support:
  1. FC++ is embedded in C++, so there is no way we can prevent anyone from using side-effects. However, our library components are all referentially transparent (by design), though there are some side-effects used "under the hood" (not visible to the outside world) for efficiency.
  2. FC++ indirect functoids are first-class values; direct functoids are not first-class, but can still be manipulated by higher-order functions using the FC++ idioms.
  3. FC++ mimics lambda through expression templates
  4. FC++ has currying combinators that make functoids curryable; all the functoids in the library support automatic currying.
  5. FC++ supports parametric polymorphism through C++ templates.
  6. C++ doesn't have automatic memory management (unless, for example, you get a garbage collector for C++) but the FC++ library (like any decent C++ library) manages its own memory, creating no extra burden for users.

Last updated on May 29, 2003 by Brian McNamara