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.
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
.
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.