Delegates

Funções como argumentos

Uma função também pode ser um parâmetro para outra função:

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

doSomething(&add); // use a função global `add` aqui
                   // add deve ter 2 parâmetros int

doer pode então ser chamado como qualquer outra função normal.

Funções locais com contexto

O exemplo acima usa o tipo function que é um ponteiro para uma função global. Assim que uma função membro ou uma função local é referenciada, os delegate devem ser usados. Trata-se de um ponteiro de função que, além disso, contém informações sobre seu contexto - ou enclosure, portanto também chamado de closure em outras linguagens. Por exemplo, um delegate que aponta para uma função membro de uma classe também inclui o ponteiro para o objeto da classe. Um delegate criado por uma função aninhada inclui um link para o contexto em vez disso. No entanto, o compilador D pode fazer automaticamente uma cópia do do contexto no heap se isso for necessário para a segurança da memória. então um delegate será vinculado a essa área de heap.

void foo() {
    void local() {
        writeln("local");
    }
    auto f = &local; // f é do tipo delegate()
}

A mesma função doSomething que recebe um delegate teria a seguinte aparência:

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.

Funções anônimas & Lambdas

Como as funções podem ser salvas como variáveis e passadas para outras funções, é trabalhoso dar a elas seu próprio nome e defini-las. Por isso, o D permite funções sem nome e lambdas de uma linha.

auto f = (int lhs, int rhs) {
    return lhs + rhs;
};
auto f = (int lhs, int rhs) => lhs + rhs; // Lambda - convertido internamente para o valor acima

Também é possível passar strings como argumentos de template para partes funcionais da biblioteca padrão do D. Por exemplo, elas oferecem uma maneira conveniente de definir um folding (também conhecido como reducer):

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

As funções de strings só são possíveis para um ou dois argumentos e usam a como o primeiro e b como o segundo argumento.

Maiores detalhes

rdmd playground.d