Delegates

Functions as arguments

A function can also be a parameter to another function:

void doSomething(int function(int, int) doer) {
    // call passed function
    doer(5,5);
}

doSomething(&add); // use global function `add` here
                   // add must have 2 int parameters

doer can then be called like any other normal function.

Local functions with context

The above example uses the function type which is a pointer to a global function. As soon as a member function or a local function is referenced, delegate's have to be used. It's a function pointer that additionally contains information about its context - or enclosure, thus also called closure in other languages. For example a delegate that points to a member function of a class also includes the pointer to the class object. A delegate created by a nested function includes a link to the enclosing context instead. However, the D compiler may automatically make a copy of the context on the heap if it is necessary for memory safety - then a delegate will link to this heap area.

void foo() {
    void local() {
        writeln("local");
    }
    auto f = &local; // f is of type delegate()
}

The same function doSomething taking a delegate would look like this:

void doSomething(int delegate(int,int) doer);

delegate and function objects cannot be mixed. But the standard function std.functional.toDelegate converts a function to a delegate.

Anonymous functions & Lambdas

As functions can be saved as variables and passed to other functions, it is laborious to give them their own name and to define them. Hence D allows nameless functions and one-line lambdas.

auto f = (int lhs, int rhs) {
    return lhs + rhs;
};
auto f = (int lhs, int rhs) => lhs + rhs; // Lambda - internally converted to the above

It is also possible to pass-in strings as template arguments to functional parts of D's standard library. For example they offer a convenient way to define a folding (aka reducer):

[1, 2, 3].reduce!`a + b`; // 6

String functions are only possible for one or two arguments and use a as the first and b as the second argument.

In-depth

rdmd playground.d