Anonymous Functions

You will receive an introduction to anonymous functions in this lesson.

Anonymous functions: Definition

The code can be more readable and concise when short functions are defined without traditional function definitions.

Anonymous functions, which are also known as function literals or lambdas, allow us to define functions inside of expressions. Anonymous functions can be used at any point where a function pointer can be used.

We will get to their shorter => syntax later below. Let’s first see their full syntax, which is usually too wordy especially when it appears inside of other expressions:

function return_type(parameters) { 
    /* operations */ 
}

For example, an object of NumberHandler that produces 7 times the numbers that are greater than 2 can be constructed by anonymous functions as in the following code:

new NumberHandler(function bool(int number) { return number > 2; }, 
                  function int(int number) { return number * 7; });

Two advantages of the code above are that the functions are not defined as proper functions and their implementations are visible right where the NumberHandler object is constructed.

Note that the anonymous function syntax is very similar to regular function syntax. Although this consistency has benefits, the full syntax of anonymous functions makes code too wordy. Therefore, there are various shorter ways of defining anonymous functions.

Shorter syntax

When the return type can be deduced from the return statement inside the anonymous function, then the return type need not be specified. The place where the return type would normally appear is highlighted by code comments.:

new NumberHandler(function /**/(int number) { return number > 2; }, 
                  function /**/(int number) { return number * 7; });

Further, when the anonymous function does not take parameters, its parameter list need not be provided. Let’s consider a function that takes a function pointer that takes nothing and returns double:

void foo(double function() func) {
    // ...
}

Anonymous functions that are passed to that function do not need have the empty parameter list. Therefore, all three of the following anonymous function syntaxes are equivalent:

foo(function double() { return 42.42; }); 
foo(function () { return 42.42; }); 
foo(function { return 42.42; });

The first one is written in the full syntax. The second one omits the return type, taking advantage of the return type deduction. The third one omits the unnecessary parameter list.

Even further, the keyword function is not needed either. In this case, it is left to the compiler to determine whether it is an anonymous function or an anonymous delegate. Unless it uses a variable from one of the enclosing scopes, it is a function:

foo({ return 42.42; });

Most anonymous functions can be defined even shorter by the lambda syntax.

Lambda syntax instead of a single return statement

In most cases, even the shortest syntax above is unnecessarily cluttered. The curly brackets that are just inside the function parameter list make the code harder to read and a return statement, Additionally, its semicolon inside a function argument looks out of place.

Let’s start with the full syntax of an anonymous function that has a single return statement:

function return_type(parameters) { return expression; }

You have already seen that the function keyword is not necessary, and the return type can be deduced:

(parameters) { return expression; }

The equivalent of that definition is the following => syntax, where the => characters replace the curly brackets, the return keyword, and the semicolon:

(parameters) => expression

The meaning of that syntax can be spelled out as “given those parameters, produce this expression (value).”

Furthermore, when there is a single parameter, the parentheses around the parameter list can also be omitted:

single_parameter => expression

On the other hand, to avoid grammar ambiguities, the parameter list must still be written as empty parentheses when there is no parameter at all:

() => expression

Programmers who know lambdas from other languages may make the mistake of using curly brackets after the => characters, which can be valid D syntax with a different meaning:

// A lambda that returns 'a + 1'
auto l0 = (int a) => a + 1

// A lambda that returns a parameter-less lambda that 
// returns 'a + 1'
auto l1 = (int a) => { return a + 1; }

assert(l0(42) == 43);
assert(l1(42)() == 43); // Executing what l1 returns

Let’s use the lambda syntax in a predicate passed to std.algorithm.filter. filter() takes a predicate as its template parameter and a range as its function parameter. It applies the predicate to each element of the range and returns the ones that satisfy the predicate. One of several ways of specifying the predicate is the lambda syntax.

Note: We will discuss ranges in a later chapter. Knowing that D slices are ranges should be sufficient.

The following lambda is a predicate that matches elements that are greater than 10:

Get hands-on with 1200+ tech skills courses.