Since Functional Programming (FP) is a paradigm, it is not limited to a specific language. You can write functional programs in any language, although it is quite ugly and tedious in some. Here I will demonstrate that the D programming language is very suitable for FP.

For the basics, D has first-class anonymous functions and closures (aka delegates).

auto square = function int(int x) { return x * x; }
int exponent = 2;
auto square = delegate int(int x)
    { return pow(x, exponent);}

There is even some syntactic sugar for lambda expressions. For example, the following is an equivalent definition.

auto square = (int x) => x * x;

The D standard library provides the standard FP convenience functions. We have to admit that currying and composition is more elegant in Haskell.

import std.algorithm: map, filter, reduce;
import std.functional: curry, memoize, compose;

Another point of FP is that objects usually are immutable. Compared to C++, the D type system provides better tools for immutability. You can qualify variables as immutable, which is similiar to C's const and Java's final, but it is transitive. Transitivity means that everything reachable by an immutable pointer is also immutable.

The D beginner is often confused that there is also const, which improves safety when casting. Basically, if you have a function which does not mutate an argument, then qualify it const, but not immutable. The point is that D does not implicitly cast something to immutable, but you can cast to const. Hence, your function can be called with mutable arguments too. In contrast, in C++ functions are often declared twice, once const and once non-const.

void foo(const int x);
const     int a = 11;
          int b = 36;
immutable int c = 42;
foo(a);
foo(b);
foo(c);

Another point that is stressed in FP is purity. In D you can mark your functions pure, which means

However, there are some pragmatic loopholes. For example, a pure function can throw exceptions (use nothrow to prevent that too), can terminate the program, can allocate heap memory (although memory management is global state), and can do impure things within a debug statement. Note that pure functions can modify their arguments and they can return mutable references. To prevent that, you can use const/immutable qualifiers.

Haskell is famous for lazyness, although that is not a strict requirement for FP. In D arguments can specifically marked for lazy evaluation. For example, the string argument for a log function is often constructed through an expression. With lazy that expression is only evaluated, if logging is enabled.

void log(lazy char[] dg) {
   if (logging)
      fwritefln(logfile, dg());
}
void foo(int i) {
   log("Entering foo() with i set to " ~ toString(i));
}

Functional programmers often boast about the safety in their language. D has a whole lot of features for safe programming. For example


Thanks to Vladimir Panteleev and Ali Çehreli for their advice. There is a discussion about this article in the D forum.

On 2015-08-19, I gave a talk about this at the Functional Programming User Group Karlsruhe. See slides as OpenDocument or exported pdf.

© 2013-04-13