Função anônima - Anonymous function

Na programação de computadores , uma função anônima ( literal de função , abstração lambda , função lambda , expressão lambda ou bloco ) é uma definição de função que não está vinculada a um identificador . As funções anônimas geralmente são argumentos passados ​​para funções de ordem superior ou usados ​​para construir o resultado de uma função de ordem superior que precisa retornar uma função. Se a função for usada apenas uma vez, ou um número limitado de vezes, uma função anônima pode ser sintaticamente mais leve do que usar uma função nomeada. Funções anônimas são onipresentes em linguagens de programação funcional e outras linguagens com funções de primeira classe , onde cumprem a mesma função para o tipo de função que os literais fazem para outros tipos de dados .

As funções anônimas têm origem no trabalho de Alonzo Church em sua invenção do cálculo lambda , no qual todas as funções são anônimas, em 1936, antes dos computadores eletrônicos. Em várias linguagens de programação, as funções anônimas são introduzidas usando a palavra-chave lambda , e as funções anônimas são freqüentemente chamadas de lambdas ou abstrações lambda. Funções anônimas têm sido uma característica das linguagens de programação desde Lisp em 1958, e um número crescente de linguagens de programação modernas suportam funções anônimas.

Nomes

Os nomes "abstração lambda", "função lambda" e "expressão lambda" referem-se à notação de abstração de função no cálculo lambda, onde a função usual f ( x ) = M seria escrita x .  M ) ( M é uma expressão que usa x ). Compare com a sintaxe Python de . lambda x: M

O nome "função seta" refere-se à matemática " mapeia para " símbolo, xM . Compare com a sintaxe JavaScript de . x => M

Usos

As funções anônimas podem ser usadas para conter funcionalidades que não precisam ser nomeadas e, possivelmente, para uso de curto prazo. Alguns exemplos notáveis ​​incluem closures e currying .

O uso de funções anônimas é uma questão de estilo. Usá-los nunca é a única maneira de resolver um problema; cada função anônima poderia, em vez disso, ser definida como uma função nomeada e chamada por nome. Alguns programadores usam funções anônimas para encapsular código específico não reutilizável sem sujar o código com muitas funções normais de uma linha.

Em algumas linguagens de programação, funções anônimas são comumente implementadas para propósitos muito específicos, como associar eventos a retornos de chamada ou instanciar a função para valores específicos, que podem ser mais eficientes, mais legíveis e menos sujeitos a erros do que chamar uma função nomeada mais genérica .

Os exemplos a seguir são escritos em Python 3.

Ordenação

Ao tentar classificar de uma maneira não padrão, pode ser mais fácil conter a lógica de classificação como uma função anônima em vez de criar uma função nomeada. A maioria das linguagens fornece uma função de classificação genérica que implementa um algoritmo de classificação que classificará objetos arbitrários. Essa função geralmente aceita uma função arbitrária que determina como comparar se dois elementos são iguais ou se um é maior ou menor que o outro.

Considere este código Python classificando uma lista de strings pelo comprimento da string:

>>> a = ['house', 'car', 'bike']
>>> a.sort(key=lambda x: len(x))
>>> a
['car', 'bike', 'house']

A função anônima neste exemplo é a expressão lambda:

lambda x: len(x)

A função anônima aceita um argumento, xe retorna o comprimento de seu argumento, que é então usado pelo sort()método como o critério de classificação.

A sintaxe básica de uma função lambda em Python é

lambda arg1, arg2, arg3, ...: <operation on the arguments returning a value>

A expressão retornada pela função lambda pode ser atribuída a uma variável e usada no código em vários lugares.

>>> add = lambda a: a + a
>>> add(20)
40

Outro exemplo seria classificar itens em uma lista pelo nome de sua classe (em Python, tudo tem uma classe):

>>> a = [10, 'number', 11.2]
>>> a.sort(key=lambda x: x.__class__.__name__)
>>> a
[11.2, 10, 'number']

Observe que 11.2tem nome de classe " float", 10tem nome de classe " int" e 'number'tem nome de classe " str". A ordem de classificação é " float", " int" e, em seguida, " str".

Fechamentos

Fechamentos são funções avaliadas em um ambiente que contém variáveis ​​associadas . O exemplo a seguir vincula a variável "limite" em uma função anônima que compara a entrada com o limite.

def comp(threshold):
    return lambda x: x < threshold

Isso pode ser usado como uma espécie de gerador de funções de comparação:

>>> func_a = comp(10)
>>> func_b = comp(20)

>>> print(func_a(5), func_a(8), func_a(13), func_a(21))
True True False False

>>> print(func_b(5), func_b(8), func_b(13), func_b(21))
True True True False

Seria impraticável criar uma função para cada função de comparação possível e pode ser muito inconveniente manter o limite próximo para uso posterior. Independentemente do motivo pelo qual um encerramento é usado, a função anônima é a entidade que contém a funcionalidade que faz a comparação.

Escovando

Currying é o processo de alterar uma função para que, em vez de receber várias entradas, pegue uma única entrada e retorne uma função que aceita a segunda entrada e assim por diante. Neste exemplo, uma função que realiza a divisão por qualquer inteiro é transformada em uma função que realiza a divisão por um conjunto inteiro.

>>> def divide(x, y):
...     return x / y

>>> def divisor(d):
...     return lambda x: divide(x, d)

>>> half = divisor(2)
>>> third = divisor(3)

>>> print(half(32), third(32))
16.0 10.666666666666666

>>> print(half(40), third(40))
20.0 13.333333333333334

Embora o uso de funções anônimas talvez não seja comum com currying, ainda pode ser usado. No exemplo acima, o divisor de função gera funções com um divisor especificado. As funções meia e terceira curry a função de divisão com um divisor fixo.

A função divisor também fecha ao vincular a variável d.

Funções de ordem superior

Uma função de ordem superior é uma função que recebe uma função como argumento. Isso é comumente usado para personalizar o comportamento de uma função definida genericamente, geralmente uma construção de loop ou esquema de recursão. Funções anônimas são uma maneira conveniente de especificar esses argumentos de função. Os exemplos a seguir estão em Python 3.

Mapa

A função de mapa executa uma chamada de função em cada elemento de uma lista. O exemplo a seguir eleva ao quadrado cada elemento em uma matriz com uma função anônima.

>>> a = [1, 2, 3, 4, 5, 6]
>>> list(map(lambda x: x*x, a))
[1, 4, 9, 16, 25, 36]

A função anônima aceita um argumento e o multiplica por si mesma (o eleva ao quadrado). A forma acima é desencorajada pelos criadores da linguagem, que sustentam que a forma apresentada a seguir tem o mesmo significado e está mais alinhada com a filosofia da linguagem:

>>> a = [1, 2, 3, 4, 5, 6]
>>> [x*x for x in a]
[1, 4, 9, 16, 25, 36]

Filtro

A função de filtro retorna todos os elementos de uma lista que é avaliada como True quando passada para uma determinada função.

>>> a = [1, 2, 3, 4, 5, 6]
>>> list(filter(lambda x: x % 2 == 0, a))
[2, 4, 6]

A função anônima verifica se o argumento transmitido a ela é par. O mesmo que com o formulário de mapa abaixo é considerado mais apropriado:

>>> a = [1, 2, 3, 4, 5, 6]
>>> [x for x in a if x % 2 == 0]
[2, 4, 6]

Dobrar

Uma função de dobra percorre todos os elementos de uma estrutura (para listas geralmente da esquerda para a direita, uma "dobra à esquerda", chamada reduceem Python), acumulando um valor conforme avança. Isso pode ser usado para combinar todos os elementos de uma estrutura em um valor, por exemplo:

>>> from functools import reduce
>>> a = [1, 2, 3, 4, 5]
>>> reduce(lambda x,y: x*y, a)
120

Isso executa

A função anônima aqui é a multiplicação dos dois argumentos.

O resultado de uma dobra não precisa ser um valor. Em vez disso, o mapa e o filtro podem ser criados usando o fold. No mapa, o valor que se acumula é uma nova lista, contendo os resultados da aplicação de uma função a cada elemento da lista original. No filtro, o valor acumulado é uma nova lista contendo apenas os elementos que correspondem à condição fornecida.

Lista de línguas

A seguir está uma lista de linguagens de programação que suportam funções anônimas não nomeadas totalmente, ou parcialmente como alguma variante, ou nem mesmo.

Esta tabela mostra algumas tendências gerais. Em primeiro lugar, as linguagens que não suportam funções anônimas ( C , Pascal , Object Pascal ) são todas linguagens tipadas estaticamente. No entanto, as linguagens digitadas estaticamente podem oferecer suporte a funções anônimas. Por exemplo, as linguagens ML são estaticamente tipadas e fundamentalmente incluem funções anônimas, e Delphi , um dialeto de Object Pascal , foi estendido para suportar funções anônimas, como o C ++ (pelo padrão C ++ 11 ). Em segundo lugar, as linguagens que tratam funções como funções de primeira classe ( Dylan , Haskell , JavaScript , Lisp , ML , Perl , Python , Ruby , Scheme ) geralmente têm suporte a funções anônimas para que as funções possam ser definidas e transmitidas tão facilmente quanto outros dados tipos.

Lista de línguas
Língua Apoio, suporte Notas
ActionScript Carrapato verdeY
Ada X vermelhoN As funções de expressão fazem parte do Ada2012
ALGOL 68 Carrapato verdeY
APL Carrapato verdeY Dyalog, ngn e dzaima APL suportam totalmente as funções dfns e tácitas. GNU APL tem suporte bastante limitado para dfns.
Linguagens de montagem X vermelhoN
Bash Carrapato verdeY Uma biblioteca foi criada para oferecer suporte a funções anônimas no Bash.
C X vermelhoN O suporte é fornecido no Clang e junto com o LLVM compiler-rt lib. O suporte GCC é fornecido para uma implementação macro que permite a possibilidade de uso. Veja abaixo para mais detalhes.
C # Carrapato verdeY
C ++ Carrapato verdeY A partir do padrão C ++ 11
CFML Carrapato verdeY A partir de Railo 4, ColdFusion 10
Clojure Carrapato verdeY
COBOL X vermelhoN O dialeto Managed COBOL não padrão da Micro Focus oferece suporte a lambdas, que são chamados de delegados / métodos anônimos.
Ondulação Carrapato verdeY
D Carrapato verdeY
Dardo Carrapato verdeY
Delphi Carrapato verdeY
Dylan Carrapato verdeY
Eiffel Carrapato verdeY
Olmo Carrapato verdeY
Elixir Carrapato verdeY
Erlang Carrapato verdeY
F # Carrapato verdeY
Excel Carrapato verdeY Função de planilha do Excel, versão beta de 2021
Fator Carrapato verdeY "Cotações" apóiam isso
Fortran X vermelhoN
Frink Carrapato verdeY
Ir Carrapato verdeY
Gosu Carrapato verdeY
Groovy Carrapato verdeY
Haskell Carrapato verdeY
Haxe Carrapato verdeY
Java Carrapato verdeY Compatível com Java 8 . Consulte a seção de limitações do Java abaixo para obter detalhes.
JavaScript Carrapato verdeY
Julia Carrapato verdeY
Kotlin Carrapato verdeY
Lisp Carrapato verdeY
Logtalk Carrapato verdeY
Lua Carrapato verdeY
CAXUMBA X vermelhoN
Mathematica Carrapato verdeY
Bordo Carrapato verdeY
MATLAB Carrapato verdeY
Maxima Carrapato verdeY
Shell de próxima geração Carrapato verdeY
Nim Carrapato verdeY
OCaml Carrapato verdeY
Oitava Carrapato verdeY
Object Pascal Carrapato verdeY Delphi, um dialeto de Object Pascal, suporta funções anônimas (formalmente, métodos anônimos ) nativamente desde Delphi 2009. O dialeto Oxygene Object Pascal também as suporta.
Objective-C (Mac OS X 10.6+) Carrapato verdeY Blocos chamados ; além do Objective-C, os blocos também podem ser usados ​​em C e C ++ durante a programação na plataforma da Apple.
OpenSCAD Carrapato verdeY O suporte literal de funções foi introduzido com a versão 2021.01.
Pascal X vermelhoN
Perl Carrapato verdeY
PHP Carrapato verdeY A partir do PHP 5.3.0, funções anônimas verdadeiras são suportadas. Anteriormente, apenas funções anônimas parciais eram suportadas, que funcionavam de maneira muito semelhante à implementação do C #.
PL / I X vermelhoN
Pitão Carrapato verdeY Python oferece suporte a funções anônimas por meio da sintaxe lambda, que oferece suporte apenas a expressões, não a instruções.
R Carrapato verdeY
Raquete Carrapato verdeY
Raku Carrapato verdeY
Rexx X vermelhoN
RPG X vermelhoN
Rubi Carrapato verdeY As funções anônimas de Ruby, herdadas de Smalltalk , são chamadas de blocos .
Ferrugem Carrapato verdeY
Scala Carrapato verdeY
Esquema Carrapato verdeY
Conversa fiada Carrapato verdeY As funções anônimas de Smalltalk são chamadas de blocos .
ML padrão Carrapato verdeY
Rápido Carrapato verdeY As funções anônimas do Swift são chamadas de Fechamentos.
TypeScript Carrapato verdeY
Tcl Carrapato verdeY
Vala Carrapato verdeY
Visual Basic .NET v9 Carrapato verdeY
Visual Prolog v 7.2 Carrapato verdeY
WLanguage v25 Carrapato verdeY A linguagem W da PCSoft usada por seu conjunto WinDev / WebDev / WinDev Mobile oferece suporte a funções anônimas a partir da versão 25 (2019)
Wolfram Language Carrapato verdeY

Exemplos

Vários idiomas oferecem suporte a funções anônimas ou algo semelhante.

APL

Apenas alguns dialetos suportam funções anônimas, seja como dfns , no estilo tácito ou uma combinação de ambos.

      f{×} ⍝ As a dfn
      f 1 2 3
1 4 9     
      g⊢×⊢   ⍝ As a tacit 3-train (fork)
      g 1 2 3
1 4 9
      h×    ⍝ As a derived tacit function
      h 1 2 3
1 4 9

C (extensão não padrão)

A função anônima não é compatível com a linguagem de programação C padrão, mas é compatível com alguns dialetos C, como GCC e Clang .

GCC

GNU Compiler Collection (GCC) suporta funções anônimas, misturadas por funções aninhadas e expressões de instrução. Possui a forma:

( { return_type anonymous_functions_name (parameters) { function_body } anonymous_functions_name; } )

O exemplo a seguir funciona apenas com GCC. Devido à forma como as macros são expandidas, o l_bodynão pode conter vírgulas fora dos parênteses; O GCC trata a vírgula como um delimitador entre os argumentos da macro. O argumento l_ret_typepode ser removido se __typeof__estiver disponível; no exemplo abaixo, usando __typeof__on array retornaria testtype *, que pode ser desreferenciado para o valor real, se necessário.

#include <stdio.h>

//* this is the definition of the anonymous function */
#define lambda(l_ret_type, l_arguments, l_body)        \
  ({                                                   \
   l_ret_type l_anonymous_functions_name l_arguments   \
   l_body                                              \
   &l_anonymous_functions_name;                        \
   })

#define forEachInArray(fe_arrType, fe_arr, fe_fn_body)                                    \
{                                                                                         \
  int i=0;                                                                                \
  for(;i<sizeof(fe_arr)/sizeof(fe_arrType);i++) {  fe_arr[i] = fe_fn_body(&fe_arr[i]); }  \
}

typedef struct
{
  int a;
  int b;
} testtype;

void printout(const testtype * array)
{
  int i;
  for ( i = 0; i < 3; ++ i )
    printf("%d %d\n", array[i].a, array[i].b);
  printf("\n");
}

int main(void)
{
  testtype array[] = { {0,1}, {2,3}, {4,5} };

  printout(array);
  /* the anonymous function is given as function for the foreach */
  forEachInArray(testtype, array,
    lambda (testtype, (void *item),
    {
      int temp = (*( testtype *) item).a;
      (*( testtype *) item).a = (*( testtype *) item).b;
      (*( testtype *) item).b = temp;
      return (*( testtype *) item);
    }));
  printout(array);
  return 0;
}

Clang (C, C ++, Objective-C, Objective-C ++)

O Clang oferece suporte a funções anônimas, chamadas de blocos , que têm a forma:

^return_type ( parameters ) { function_body }

O tipo dos blocos acima é return_type (^)(parameters).

Usando a extensão de blocos mencionada anteriormente e o Grand Central Dispatch (libdispatch), o código poderia parecer mais simples:

#include <stdio.h>
#include <dispatch/dispatch.h>

int main(void) {
  void (^count_loop)() = ^{
    for (int i = 0; i < 100; i++)
      printf("%d\n", i);
    printf("ah ah ah\n");
  };

/* Pass as a parameter to another function */
  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), count_loop);

/* Invoke directly */
  count_loop();

  return 0;
}

O código com blocos deve ser compilado -fblockse vinculado a-lBlocksRuntime

C ++ (desde C ++ 11)

C ++ 11 oferece suporte a funções anônimas, chamadas de expressões lambda , que têm a forma:

[capture](parameters) -> return_type { function_body }

Este é um exemplo de expressão lambda:

[](int x, int y) { return x + y; }

C ++ 11 também oferece suporte a encerramentos , aqui chamados de capturas. As capturas são definidas entre colchetes [e ]na declaração da expressão lambda. O mecanismo permite que essas variáveis ​​sejam capturadas por valor ou por referência. A tabela a seguir demonstra isso:

[]        // No captures, the lambda is implicitly convertible to a function pointer.
[x, &y]   // x is captured by value and y is captured by reference.
[&]       // Any external variable is implicitly captured by reference if used
[=]       // Any external variable is implicitly captured by value if used.
[&, x]    // x is captured by value. Other variables will be captured by reference.
[=, &z]   //z is captured by reference. Other variables will be captured by value.

Variáveis ​​capturadas por valor são constantes por padrão. Adicionar mutabledepois da lista de parâmetros os torna não constantes.

Os dois exemplos a seguir demonstram o uso de uma expressão lambda:

std::vector<int> some_list{ 1, 2, 3, 4, 5 };
int total = 0;
std::for_each(begin(some_list), end(some_list), 
              [&total](int x) {	total += x; }); 
// Note that std::accumulate would be a way better alternative here...

Isso calcula o total de todos os elementos da lista. A variável totalé armazenada como parte do encerramento da função lambda. Como é uma referência à variável da pilha total, ele pode alterar seu valor.

std::vector<int> some_list{ 1, 2, 3, 4, 5 };
int total = 0;
int value = 5;
std::for_each(begin(some_list), end(some_list), 
             [&total, value, this](int x) { total += x * value * this->some_func(); });

Isso fará com totalque seja armazenado como uma referência, mas valueserá armazenado como uma cópia.

A captura de thisé especial. Só pode ser capturado por valor, não por referência. thissó pode ser capturado se a função envolvente mais próxima for uma função de membro não estática. O lambda terá o mesmo acesso que o membro que o criou, em termos de membros protegidos / privados.

Se thisfor capturado, explícita ou implicitamente, o escopo dos membros da classe incluídos também será testado. Acessar membros de thisnão requer o uso explícito de this->sintaxe.

A implementação interna específica pode variar, mas a expectativa é que uma função lambda que captura tudo por referência armazenará o ponteiro da pilha real da função em que foi criada, em vez de referências individuais às variáveis ​​da pilha. No entanto, como a maioria das funções lambda são pequenas e locais em escopo, elas são provavelmente candidatas para in- line e, portanto, não precisam de armazenamento adicional para referências.

Se um objeto de fechamento contendo referências a variáveis ​​locais for chamado após o escopo do bloco mais interno de sua criação, o comportamento será indefinido .

As funções lambda são objetos de função de um tipo dependente de implementação; o nome desse tipo está disponível apenas para o compilador. Se o usuário deseja usar uma função lambda como parâmetro, o tipo de parâmetro deve ser um tipo de modelo ou ele deve criar um std::functionobjeto semelhante para capturar o valor lambda. O uso da autopalavra - chave pode ajudar a armazenar a função lambda,

auto my_lambda_func = [&](int x) { /*...*/ };
auto my_onheap_lambda_func = new auto([=](int x) { /*...*/ });

Aqui está um exemplo de armazenamento de funções anônimas em variáveis, vetores e matrizes; e passando-os como parâmetros nomeados:

#include <functional>
#include <iostream>
#include <vector>

double eval(std::function<double(double)> f, double x = 2.0) {
  return f(x);
}

int main() {
  std::function<double(double)> f0 = [](double x) { return 1; };
  auto f1 = [](double x) { return x; };
  decltype(f0) fa[3] = {f0, f1, [](double x) { return x * x; }};
  std::vector<decltype(f0)> fv = {f0, f1};
  fv.push_back([](double x) { return x * x; });
  for (size_t i = 0; i < fv.size(); i++) {
    std::cout << fv[i](2.0) << std::endl;
  }
  for (size_t i = 0; i < 3; i++) {
    std::cout << fa[i](2.0) << std::endl;
  }
  for (auto& f : fv) {
    std::cout << f(2.0) << std::endl;
  }
  for (auto& f : fa) {
    std::cout << f(2.0) << std::endl;
  }
  std::cout << eval(f0) << std::endl;
  std::cout << eval(f1) << std::endl;
  std::cout << eval([](double x) { return x * x; }) << std::endl;
}

Uma expressão lambda com uma especificação de captura vazia ( []) pode ser convertida implicitamente em um ponteiro de função com o mesmo tipo com que o lambda foi declarado. Portanto, isso é legal:

auto a_lambda_func = [](int x) { /*...*/ };
void (* func_ptr)(int) = a_lambda_func;
func_ptr(4); //calls the lambda.

A biblioteca Boost também fornece sua própria sintaxe para funções lambda, usando a seguinte sintaxe:

for_each(a.begin(), a.end(), std::cout << _1 << ' ');

C #

Em C # , o suporte para funções anônimas foi aprofundado por meio das várias versões do compilador de linguagem. A linguagem v3.0, lançada em novembro de 2007 com .NET Framework v3.5, tem suporte total para funções anônimas. C # os nomeia como expressões lambda , seguindo a versão original das funções anônimas, o cálculo lambda .

// the first int is the x' type
// the second int is the return type
// <see href="http://msdn.microsoft.com/en-us/library/bb549151.aspx" />
Func<int,int> foo = x => x * x;
Console.WriteLine(foo(7));

Embora a função seja anônima, ela não pode ser atribuída a uma variável digitada implicitamente, porque a sintaxe lambda pode ser usada para denotar uma função anônima ou uma árvore de expressão, e a escolha não pode ser decidida automaticamente pelo compilador. Por exemplo, isso não funciona:

// will NOT compile!
var foo = (int x) => x * x;

No entanto, uma expressão lambda pode tomar parte na inferência de tipo e pode ser usada como um argumento de método , por exemplo, para usar funções anônimas com o recurso Map disponível com System.Collections.Generic.List(no ConvertAll()método):

// Initialize the list:
var values = new List<int>() { 7, 13, 4, 9, 3 };
// Map the anonymous function over all elements in the list, return the new list
var foo = values.ConvertAll(d => d * d) ; 
// the result of the foo variable is of type System.Collections.Generic.List<Int32>

As versões anteriores do C # tinham suporte mais limitado para funções anônimas. C # v1.0, introduzido em fevereiro de 2002 com o .NET Framework v1.0, fornecia suporte de função anônima parcial por meio do uso de delegados . Essa construção é um tanto semelhante aos delegados PHP. No C # 1.0, os delegados são como ponteiros de função que se referem a um método nomeado explicitamente dentro de uma classe. (Mas, ao contrário do PHP, o nome é desnecessário no momento em que o delegado é usado.) C # v2.0, lançado em novembro de 2005 com o .NET Framework v2.0, introduziu o conceito de métodos anônimos como uma forma de escrever instruções inline não nomeadas blocos que podem ser executados em uma invocação de delegado. C # 3.0 continua a oferecer suporte a essas construções, mas também oferece suporte à construção de expressão lambda.

Este exemplo será compilado em C # 3.0 e exibe as três formas:

    public class TestDriver
    {
        delegate int SquareDelegate(int d);
        static int Square(int d)
        {
            return d * d;
        }
 
        static void Main(string[] args)
        {
            // C# 1.0: Original delegate syntax needed 
            // initializing with a named method.
            SquareDelegate A = new SquareDelegate(Square);
            System.Console.WriteLine(A(3));
 
            // C# 2.0: A delegate can be initialized with
            // inline code, called an "anonymous method". This
            // method takes an int as an input parameter.
            SquareDelegate B = delegate(int d) { return d * d; };
            System.Console.WriteLine(B(5));
 
            // C# 3.0. A delegate can be initialized with
            // a lambda expression. The lambda takes an int, and returns an int. 
            // The type of x is inferred by the compiler.
            SquareDelegate C = x => x * x;
            System.Console.WriteLine(C(7));
 
            // C# 3.0. A delegate that accepts one input and
            // returns one output can also be implicitly declared with the Func<> type.
            System.Func<int,int> D = x => x * x;
            System.Console.WriteLine(D(9));
        } 
    }

No caso da versão C # 2.0, o compilador C # pega o bloco de código da função anônima e cria uma função privada estática. Internamente, a função recebe um nome gerado, é claro; este nome gerado é baseado no nome do método no qual o Delegado é declarado. Mas o nome não é exposto ao código do aplicativo, exceto pelo uso de reflexão .

No caso da versão C # 3.0, o mesmo mecanismo se aplica.

ColdFusion Markup Language (CFML)

Usando o função palavra-chave:

fn = function(){
  // statements
};

Ou usando uma função de seta:

fn = () => {
  // statements
};

fn = () => singleExpression // singleExpression is implicitly returned. There is no need for the braces or the return keyword

fn = singleParam => { // if the arrow function has only one parameter, there's no need for parentheses
    // statements
}

fn = (x, y) => { // if the arrow function has zero or multiple parameters, one needs to use parentheses
    // statements
}

CFML oferece suporte a quaisquer instruções dentro da definição da função, não simplesmente expressões.

CFML oferece suporte a funções anônimas recursivas:

factorial = function(n){
    return n > 1 ? n * factorial(n-1) : 1;
};

As funções anônimas CFML implementam o fechamento.

D

D usa delegados embutidos para implementar funções anônimas. A sintaxe completa para um delegado inline é

return_type delegate(arguments){/*body*/}

Se não houver ambigüidade, o tipo de retorno e o delegado de palavra-chave podem ser omitidos.

(x){return x*x;}
delegate (x){return x*x;} // if more verbosity is needed
(int x){return x*x;} // if parameter type cannot be inferred
delegate (int x){return x*x;} // ditto
delegate double(int x){return x*x;} // if return type must be forced manually

Desde a versão 2.0, D aloca fechamentos no heap, a menos que o compilador possa provar que é desnecessário; a scopepalavra - chave pode ser usada para forçar a alocação da pilha. Desde a versão 2.058, é possível usar a notação abreviada:

x => x*x;
(int x) => x*x;
(x,y) => x*y;
(int x, int y) => x*y;

Uma função anônima pode ser atribuída a uma variável e usada assim:

auto sqr = (double x){return x*x;};
double y = sqr(4);

Dardo

O Dart oferece suporte a funções anônimas.

var sqr = (x) => x * x;
print(sqr(5));

ou

print(((x) => x * x)(5));

Delphi

Delphi introduziu funções anônimas na versão 2009.

program demo;

type
  TSimpleProcedure = reference to procedure;
  TSimpleFunction = reference to function(const x: string): Integer;

var
  x1: TSimpleProcedure;
  y1: TSimpleFunction;

begin
  x1 := procedure
    begin
      Writeln('Hello World');
    end;
  x1;   //invoke anonymous method just defined

  y1 := function(const x: string): Integer
    begin
      Result := Length(x);
    end;
  Writeln(y1('bar')); 
end.

PascalABC.NET

PascalABC.NET suporta funções anônimas usando sintaxe lambda

begin
  var n := 10000000;
  var pp := Range(1,n)
    .Select(x->Rec(Random(),Random()))
    .Where(p->sqr(p.Item1)+sqr(p.Item2)<1)
    .Count/n*4;
  Print(pp);
end.

Elixir

Elixir usa o encerramento fn para funções anônimas.

sum = fn(a, b) -> a + b end
sum.(4, 3)
#=> 7

square = fn(x) -> x * x end
Enum.map [1, 2, 3, 4], square
#=> [1, 4, 9, 16]

Erlang

Erlang usa uma sintaxe para funções anônimas semelhante à de funções nomeadas.

% Anonymous function bound to the Square variable
Square = fun(X) -> X * X end.

% Named function with the same functionality
square(X) -> X * X.

Ir

Go oferece suporte a funções anônimas.

foo := func(x int) int {
	return x * x
}
fmt.Println(foo(10))

Haskell

Haskell usa uma sintaxe concisa para funções anônimas (expressões lambda). A barra invertida deve ser semelhante a λ.

\x -> x * x

As expressões lambda são totalmente integradas com o mecanismo de inferência de tipo e suportam toda a sintaxe e recursos das funções "comuns" (exceto para o uso de várias definições para correspondência de padrões, uma vez que a lista de argumentos é especificada apenas uma vez).

map (\x -> x * x) [1..5] -- returns [1, 4, 9, 16, 25]

Os seguintes são todos equivalentes:

f x y = x + y
f x = \y -> x + y
f = \x y -> x + y

Haxe

No Haxe , as funções anônimas são chamadas de lambda e usam a sintaxe function(argument-list) expression;.

var f = function(x) return x*x;
f(8); // 64

(function(x,y) return x+y)(5,6); // 11

Java

Java suporta funções anônimas, chamadas Lambda Expressions , começando com JDK 8 .

Uma expressão lambda consiste em uma lista separada por vírgulas dos parâmetros formais entre parênteses, um símbolo de seta ( ->) e um corpo. Os tipos de dados dos parâmetros sempre podem ser omitidos, assim como os parênteses se houver apenas um parâmetro. O corpo pode consistir em uma declaração ou um bloco de declaração.

// with no parameter
() -> System.out.println("Hello, world.")

// with one parameter (this example is an identity function).
a -> a

// with one expression
(a, b) -> a + b

// with explicit type information
(long id, String name) -> "id: " + id + ", name:" + name

// with a code block
(a, b) -> { return a + b; }

// with multiple statements in the lambda body. It needs a code block.
// This example also includes two nested lambda expressions (the first one is also a closure).
(id, defaultPrice) -> {
    Optional<Product> product = productList.stream().filter(p -> p.getId() == id).findFirst();
    return product.map(p -> p.getPrice()).orElse(defaultPrice);
}

Expressões lambda são convertidas em "interfaces funcionais" (definidas como interfaces que contêm apenas um método abstrato, além de um ou mais métodos padrão ou estáticos), como no exemplo a seguir:

public class Calculator {
    interface IntegerMath {
        int operation(int a, int b);

        default IntegerMath swap() {
            return (a, b) -> operation(b, a);
        }
    }

    private static int apply(int a, int b, IntegerMath op) {
        return op.operation(a, b);
    }

    public static void main(String... args) {
        IntegerMath addition = (a, b) -> a + b;
        IntegerMath subtraction = (a, b) -> a - b;
        System.out.println("40 + 2 = " + apply(40, 2, addition));
        System.out.println("20 - 10 = " + apply(20, 10, subtraction));
        System.out.println("10 - 20 = " + apply(20, 10, subtraction.swap()));    
    }
}

Neste exemplo, uma interface funcional chamada IntegerMathé declarada. As expressões lambda que implementam IntegerMathsão passadas para o apply()método a ser executado. Métodos padrão, como swapdefinir métodos em funções.

Java 8 introduziu outro mecanismo denominado referência de método (o ::operador) para criar um lambda em um método existente. Uma referência de método não indica o número ou tipos de argumentos porque eles são extraídos do método abstrato da interface funcional.

IntBinaryOperator sum = Integer::sum;

No exemplo acima, a interface funcional IntBinaryOperatordeclara um método abstrato int applyAsInt(int, int), então o compilador procura um método int sum(int, int)na classe java.lang.Integer.

Limitações de Java

Os lambdas do Java 8 têm as seguintes limitações:

  • Lambdas podem lançar exceções verificadas, mas tais lambdas não funcionarão com as interfaces usadas pela API Collection.
  • Variáveis ​​que estão no escopo onde o lambda é declarado só podem ser acessadas dentro do lambda se forem efetivamente finais, ou seja, se a variável não for modificada dentro ou fora do escopo lambda.

JavaScript

JavaScript / ECMAScript oferece suporte a funções anônimas.

alert((function(x){
  return x * x;
})(10));

ES6 suporta a sintaxe de "função de seta", onde um símbolo => separa a lista de parâmetros da função anônima do corpo:

alert((x => x * x)(10));

Essa construção é freqüentemente usada em Bookmarklets . Por exemplo, para alterar o título do documento atual (visível na barra de título da janela ) para seu URL , o seguinte bookmarklet pode parecer funcionar.

javascript:document.title=location.href;

No entanto, como a instrução de atribuição retorna um valor (a própria URL), muitos navegadores realmente criam uma nova página para exibir esse valor.

Em vez disso, uma função anônima, que não retorna um valor, pode ser usada:

javascript:(function(){document.title=location.href;})();

A instrução de função no primeiro par (externo) de parênteses declara uma função anônima, que é então executada quando usada com o último par de parênteses. Isso é quase equivalente ao seguinte, que preenche o ambiente com fuma função anônima diferente.

javascript:var f = function(){document.title=location.href;}; f();

Use void () para evitar novas páginas para funções anônimas arbitrárias:

javascript:void(function(){return document.title=location.href;}());

ou apenas:

javascript:void(document.title=location.href);

JavaScript tem sutilezas sintáticas para a semântica de definir, invocar e avaliar funções anônimas. Essas nuances subliminares são uma consequência direta da avaliação das expressões entre parênteses. As seguintes construções, chamadas de expressão de função invocada imediatamente, ilustram isso:

(function(){ ... }())

e

(function(){ ... })()

Representando " function(){ ... }" por f, a forma das construções é um parênteses dentro de um parêntese (f())e um parêntese aplicado a um parênteses (f)().

Observe a ambigüidade sintática geral de uma expressão entre parênteses, argumentos entre parênteses para uma função e os parênteses em torno dos parâmetros formais em uma definição de função. Em particular, JavaScript define um ,operador (vírgula) no contexto de uma expressão entre parênteses. Não é mera coincidência que as formas sintáticas coincidam para uma expressão e os argumentos de uma função (ignorando a sintaxe do parâmetro formal da função)! Se fnão for identificado nas construções acima, eles se tornam (())e ()(). O primeiro não fornece nenhuma dica sintática de qualquer função residente, mas o segundo DEVE avaliar o primeiro entre parênteses como uma função para ser JavaScript legal. (À parte: por exemplo, o ()'s poderia ser ([], {}, 42, "abc", função () {}) desde que a expressão seja avaliada como uma função.)

Além disso, uma função é uma instância de Object (da mesma forma, os objetos são instâncias de Function) e os colchetes de notação literal do objeto, {}para código entre chaves , são usados ​​ao definir uma função dessa maneira (em oposição ao uso new Function(...)). Em um sentido não rigoroso muito amplo (especialmente desde que as ligações globais estão comprometidas), uma sequência arbitrária de instruções JavaScript reforçadas,, {stuff}pode ser considerada um ponto fixo de

(function(){( function(){( ... {( function(){stuff}() )} ... )}() )}() )

Mais corretamente, mas com ressalvas,

( function(){stuff}() ) ~=
   A_Fixed_Point_of(
      function(){ return function(){ return ... { return function(){stuff}() } ... }() }()
   )

Observe as implicações da função anônima nos fragmentos de JavaScript a seguir:

  • function(){ ... }()sem o envolvente ()geralmente não é legal
  • (f=function(){ ... })não "esquece" fglobalmente ao contrário(function f(){ ... })
As métricas de desempenho para analisar as complexidades de espaço e tempo de chamadas de função, pilha de chamadas, etc. em um mecanismo interpretador JavaScript são implementadas facilmente com essas últimas construções de função anônima. A partir das implicações dos resultados, é possível deduzir alguns dos detalhes de implementação recursiva versus iterativa de um mecanismo, especialmente a recursão de cauda .

Julia

Em Julia funções anônimas são definidas usando a sintaxe (arguments)->(expression),

julia> f = x -> x*x; f(8)
64
julia> ((x,y)->x+y)(5,6)
11

Lisp

Lisp e Scheme suportam funções anônimas usando a construção "lambda", que é uma referência ao cálculo lambda . Clojure oferece suporte a funções anônimas com a forma especial "fn" e a sintaxe do leitor # ().

(lambda (arg) (* arg arg))

Lisp Comum

Common Lisp tem o conceito de expressões lambda. Uma expressão lambda é escrita como uma lista com o símbolo "lambda" como seu primeiro elemento. A lista contém então a lista de argumentos, documentação ou declarações e um corpo de função. Expressões lambda podem ser usadas dentro de formas lambda e com o operador especial "função".

(function (lambda (arg) (do-something arg)))

"função" pode ser abreviada como # '. Além disso, existe a macro lambda , que se expande em uma forma de função:

; using sharp quote
#'(lambda (arg) (do-something arg))
; using the lambda macro:
(lambda (arg) (do-something arg))

Um uso típico de funções anônimas em Common Lisp é passá-las para funções de ordem superior como mapcar , que aplica uma função a cada elemento de uma lista e retorna uma lista dos resultados.

(mapcar #'(lambda (x) (* x x))
        '(1 2 3 4))
; -> (1 4 9 16)

A forma lambda no Common Lisp permite que uma expressão lambda seja escrita em uma chamada de função:

((lambda (x y)
   (+ (sqrt x) (sqrt y)))
 10.0
 12.0)

Funções anônimas em Common Lisp também podem receber nomes globais posteriormente:

(setf (symbol-function 'sqr)
      (lambda (x) (* x x)))
; which allows us to call it using the name SQR:
(sqr 10.0)

Esquema

As funções nomeadas de Scheme são simplesmente um açúcar sintático para funções anônimas vinculadas a nomes:

(define (somename arg)
  (do-something arg))

expande (e é equivalente) a

(define somename
  (lambda (arg)
    (do-something arg)))

Clojure

Clojure oferece suporte a funções anônimas por meio do formulário especial "fn":

(fn [x] (+ x 3))

Também existe uma sintaxe de leitor para definir um lambda:

#(+ % %2%3) ; Defines an anonymous function that takes three arguments and sums them.

Como Scheme, as "funções nomeadas" de Clojure são simplesmente açúcar sintático para lambdas vinculadas a nomes:

(defn func [arg] (+ 3 arg))

expande para:

(def func (fn [arg] (+ 3 arg)))

Lua

Em Lua (assim como em Scheme), todas as funções são anônimas. Uma função nomeada em Lua é simplesmente uma variável que contém uma referência a um objeto de função.

Assim, em Lua

function foo(x) return 2*x end

é apenas açúcar sintático para

foo = function(x) return 2*x end

Um exemplo de uso de funções anônimas para classificação de ordem reversa:

table.sort(network, function(a,b)
  return a.name > b.name
end)

Wolfram Language, Mathematica

A Wolfram Language é a linguagem de programação do Mathematica . As funções anônimas são importantes na programação do último. Existem várias maneiras de criá-los. Abaixo estão algumas funções anônimas que incrementam um número. O primeiro é o mais comum. #1refere-se ao primeiro argumento e &marca o fim da função anônima.

     #1+1&
     Function[x,x+1]
     x \[Function] x+1

Então, por exemplo:

    f:= #1^2&;f[8]
     64
    #1+#2&[5,6]
     11

Além disso, o Mathematica adicionou uma construção para criar funções anônimas recursivas. O símbolo '# 0' refere-se a toda a função. A função a seguir calcula o fatorial de sua entrada:

     If[#1 == 1, 1, #1 * #0[#1-1]]&

Por exemplo, 6 fatorial seria:

     If[#1 == 1, 1, #1 * #0[#1-1]]&[6]
720

MATLAB, Octave

Funções anônimas em MATLAB ou Octave são definidas usando a sintaxe @(argument-list)expression. Quaisquer variáveis ​​que não sejam encontradas na lista de argumentos são herdadas do escopo delimitador e são capturadas por valor.

>> f = @(x)x*x; f(8)
ans =  64
>> (@(x,y)x+y)(5,6) % Only works in Octave
ans =  11

Maxima

No Maxima funções anônimas são definidas usando a sintaxe lambda(argument-list,expression),

 f: lambda([x],x*x); f(8);
 64

 lambda([x,y],x+y)(5,6);
 11

ML

Os vários dialetos do ML suportam funções anônimas.

OCaml

Funções anônimas em OCaml são funções sem um nome declarado. Aqui está um exemplo de uma função anônima que multiplica sua entrada por dois:

fun x -> x*2

No exemplo, fun é uma palavra-chave que indica que a função é uma função anônima. Estamos passando um argumento xe -> para separar o argumento do corpo.

F #

F # oferece suporte a funções anônimas, da seguinte maneira:

(fun x -> x * x) 20 // 400

ML padrão

ML padrão oferece suporte a funções anônimas, da seguinte maneira:

fn  arg => arg * arg

Shell de próxima geração

O Next Generation Shell tem várias sintaxes para funções anônimas devido à sua prevalência na linguagem e diferentes casos de uso.

Sintaxes:

f = X*X; f(8)                       # Result: 64
f = { A*B+C }; f(2,3,4)             # Result: 10
f = F(x:Int, y:Int) x*y+2; f(3, 4)  # Result: 14

f = "${X} is all about ${Y}"
f("programming", "semantics")       # Result: "programming is all about semantics"

Exemplos de uso de funções anônimas:

[0,1,2].map(X*2)                    # Result: [0,2,4]

data = {"a": "xxx", "b": "yyy"}
data.map("${X} is ${Y}")            # Result: ["a is xxx", "b is yyy"]

Nim

O Nim oferece suporte a funções anônimas de múltiplas linhas e múltiplas expressões.

var anon = proc (var1, var2: int): int = var1 + var2
assert anon(1, 2) == 3

Exemplo de várias linhas:

var anon = func (x: int): bool =
             if x > 0:
               result = true
             else: 
               result = false

assert anon(9)

Funções anônimas podem ser passadas como parâmetros de entrada de outras funções:

var cities = @["Frankfurt", "Tokyo", "New York"]

cities.sort(
  proc (x, y: string): int = cmp(x.len, y.len)
)

Uma função anônima é basicamente uma função sem nome.

Perl

Perl 5

Perl 5 oferece suporte a funções anônimas, da seguinte maneira:

(sub { print "I got called\n" })->();         # 1. fully anonymous, called as created

my $squarer = sub { my $x = shift; $x * $x }; # 2. assigned to a variable

sub curry {
    my ($sub, @args) = @_;
    return sub { $sub->(@args, @_) };         # 3. as a return value of another function
}

# example of currying in Perl programming
sub sum { my $tot = 0; $tot += $_ for @_; $tot } # returns the sum of its arguments
my $curried = curry \&sum, 5, 7, 9;
print $curried->(1,2,3), "\n";    # prints 27 ( = 5 + 7 + 9 + 1 + 2 + 3 )

Outras construções usam blocos vazios como argumentos, que servem a uma função semelhante às funções lambda de um parâmetro, mas não têm a mesma convenção de passagem de parâmetro que as funções - @_ não é definido.

my @squares = map { $_ * $_ } 1..10;   # map and grep don't use the 'sub' keyword
my @square2 = map $_ * $_, 1..10;      # braces unneeded for one expression

my @bad_example = map { print for @_ } 1..10; # values not passed like normal Perl function

PHP

Antes do 4.0.1, o PHP não tinha suporte para funções anônimas.

PHP 4.0.1 a 5.3

PHP 4.0.1 introduziu o create_functionque era o suporte inicial a funções anônimas. Esta chamada de função cria uma nova função nomeada aleatoriamente e retorna seu nome (como uma string)

$foo = create_function('$x', 'return $x*$x;');
$bar = create_function("\$x", "return \$x*\$x;");
echo $foo(10);

A lista de argumentos e o corpo da função devem estar entre aspas simples ou os cifrões devem ter escape. Caso contrário, o PHP assume que " $x" significa a variável $xe irá substituí-la na string (apesar de possivelmente não existir) ao invés de deixar " $x" na string. Para funções com aspas ou funções com muitas variáveis, pode ser bastante tedioso garantir que o corpo da função pretendida seja o que o PHP interpreta.

Cada invocação de create_functioncria uma nova função, que existe para o resto do programa, e não pode ser coletada como lixo , usando a memória do programa de forma irreversível. Se isso for usado para criar funções anônimas muitas vezes, por exemplo, em um loop, pode causar problemas como o inchaço da memória.

PHP 5.3

PHP 5.3 adicionou uma nova classe chamada Closuree método mágico __invoke()que torna uma instância de classe invocável.

$x = 3;
$func = function($z) { return $z * 2; };
echo $func($x); // prints 6

Neste exemplo, $funcé uma instância de Closuree echo $func($x)é equivalente a echo $func->__invoke($x). PHP 5.3 imita funções anônimas, mas não suporta funções anônimas verdadeiras porque funções PHP ainda não são objetos de primeira classe.

PHP 5.3 oferece suporte a encerramentos, mas as variáveis ​​devem ser explicitamente indicadas como tais:

$x = 3;
$func = function() use(&$x) { $x *= 2; };
$func();
echo $x; // prints 6

A variável $xé vinculada por referência, portanto, a invocação de $funcmodifica-a e as alterações são visíveis fora da função.

PHP 7.4

As funções de seta foram introduzidas no PHP 7.4

$x = 3;
$func = fn($z) => $z * 2;
echo $func($x); // prints 6

Dialetos do Prolog

Logtalk

Logtalk usa a seguinte sintaxe para predicados anônimos (expressões lambda):

{FreeVar1, FreeVar2, ...}/[LambdaParameter1, LambdaParameter2, ...]>>Goal

Um exemplo simples sem variáveis ​​livres e usando um predicado de mapeamento de lista é:

| ?- meta::map([X,Y]>>(Y is 2*X), [1,2,3], Ys).
Ys = [2,4,6]
yes

Currying também é suportado. O exemplo acima pode ser escrito como:

| ?- meta::map([X]>>([Y]>>(Y is 2*X)), [1,2,3], Ys).
Ys = [2,4,6]
yes

Visual Prolog

Funções anônimas (em geral predicados anônimos ) foram introduzidas no Visual Prolog na versão 7.2. Predicados anônimos podem capturar valores do contexto. Se criado em um membro do objeto, ele também pode acessar o estado do objeto (por captura This).

mkAdderretorna uma função anônima, que capturou o argumento Xno encerramento. A função retornada é uma função que adiciona Xao seu argumento:

clauses
    mkAdder(X) = { (Y) = X+Y }.

Pitão

Python suporta funções anônimas simples por meio da forma lambda. O corpo executável do lambda deve ser uma expressão e não pode ser uma instrução, o que é uma restrição que limita sua utilidade. O valor retornado pelo lambda é o valor da expressão contida. As formas lambda podem ser usadas em qualquer lugar que as funções comuns possam. No entanto, essas restrições o tornam uma versão muito limitada de uma função normal. Aqui está um exemplo:

>>> foo = lambda x: x * x
>>> foo(10)
100

Em geral, a convenção Python incentiva o uso de funções nomeadas definidas no mesmo escopo que normalmente usamos funções anônimas em outras linguagens. Isso é aceitável, pois as funções definidas localmente implementam todo o poder dos encerramentos e são quase tão eficientes quanto o uso de um lambda em Python. Neste exemplo, pode-se dizer que a função de energia embutida foi curry :

>>> def make_pow(n):
...     def fixed_exponent_pow(x):
...         return pow(x, n)
...     return fixed_exponent_pow
...
>>> sqr = make_pow(2)
>>> sqr(10)
100
>>> cub = make_pow(3)
>>> cub(10)
1000

R

Em R, as funções anônimas são definidas usando a sintaxe function(argument-list)expression.

> f <- function(x)x*x; f(8)
[1] 64
> (function(x,y)x+y)(5,6)
[1] 11

Raku

No Raku , todos os blocos (mesmo aqueles associados a if, while, etc.) são funções anônimas. Um bloco que não é usado como um rvalue é executado imediatamente.

  1. totalmente anônimo, chamado como criado
    { say "I got called" };
    
  2. atribuído a uma variável
    my $squarer1 = -> $x { $x * $x };             # 2a. pointy block
    my $squarer2 = { $^x * $^x };                 # 2b. twigil
    my $squarer3 = { my $x = shift @_; $x * $x }; # 2c. Perl 5 style
    
  3. escovando
    sub add ($m, $n) { $m + $n }
    my $seven   = add(3, 4);
    my $add_one = &add.assuming(m => 1);
    my $eight   = $add_one($seven);
    
  4. Objeto WhateverCode
    my $w = * - 1;       # WhateverCode object
    my $b = { $_ - 1 };  # same functionality, but as Callable block
    

Rubi

Ruby suporta funções anônimas usando uma estrutura sintática chamada bloco . Existem dois tipos de dados para blocos em Ruby. Procs se comportam de maneira semelhante a fechamentos , enquanto lambdas se comportam de maneira mais análoga a uma função anônima. Quando passado para um método, um bloco é convertido em um Proc em algumas circunstâncias.

irb(main):001:0> # Example 1:
irb(main):002:0* # Purely anonymous functions using blocks.
irb(main):003:0* ex = [16.2, 24.1, 48.3, 32.4, 8.5]
=> [16.2, 24.1, 48.3, 32.4, 8.5]
irb(main):004:0> ex.sort_by { |x| x - x.to_i } # Sort by fractional part, ignoring integer part.
=> [24.1, 16.2, 48.3, 32.4, 8.5]
irb(main):005:0> # Example 2:
irb(main):006:0* # First-class functions as an explicit object of Proc -
irb(main):007:0* ex = Proc.new { puts "Hello, world!" }
=> #<Proc:0x007ff4598705a0@(irb):7>
irb(main):008:0> ex.call
Hello, world!
=> nil
irb(main):009:0> # Example 3:
irb(main):010:0* # Function that returns lambda function object with parameters
irb(main):011:0* def is_multiple_of(n)
irb(main):012:1>   lambda{|x| x % n == 0}
irb(main):013:1> end
=> nil
irb(main):014:0> multiple_four = is_multiple_of(4)
=> #<Proc:0x007ff458b45f88@(irb):12 (lambda)>
irb(main):015:0> multiple_four.call(16)
=> true
irb(main):016:0> multiple_four[15]
=> false

Ferrugem

No Rust , as funções anônimas são chamadas de fechamentos. Eles são definidos usando a seguinte sintaxe:

|<parameter-name>: <type>| -> <return-type> { <body> };

Por exemplo:

let f = |x: i32| -> i32 { x * 2 };

Com a inferência de tipo, no entanto, o compilador é capaz de inferir o tipo de cada parâmetro e o tipo de retorno, portanto, o formulário acima pode ser escrito como:

let f = |x| { x * 2 };

Com fechamentos com uma única expressão (ou seja, um corpo com uma linha), as chaves podem ser omitidas:

let f = |x| x * 2;

Fechamentos sem parâmetro de entrada são escritos assim:

let f = || println!("Hello, world!");

Os fechamentos podem ser passados ​​como parâmetros de entrada de funções que esperam um ponteiro de função:

// A function which takes a function pointer as an argument and calls it with
// the value `5`.
fn apply(f: fn(i32) -> i32) -> i32 {
    // No semicolon to indicate an implicit return
    f(5)
}

fn main() {
    // Defining the closure
    let f = |x| x * 2;

    println!("{}", apply(f));  // 10
    println!("{}", f(5));      // 10
}

No entanto, podem ser necessárias regras complexas para descrever como os valores no corpo da tampa são capturados. Eles são implementados usando o Fn, FnMute FnOncetraços:

  • Fn: o fechamento captura por referência ( &T). Eles são usados ​​para funções que ainda podem ser chamadas se tiverem acesso de referência (com &) a seu ambiente.
  • FnMut: o fechamento captura por referência mutável ( &mut T). Eles são usados ​​para funções que podem ser chamadas se tiverem acesso de referência mutável (com &mut) a seu ambiente.
  • FnOnce: o fechamento captura por valor ( T). Eles são usados ​​para funções que são chamadas apenas uma vez.

Com essas características, o compilador irá capturar as variáveis ​​da maneira menos restritiva possível. Eles ajudam a controlar como os valores são movidos entre os escopos, o que é muito importante, pois o Rust segue uma construção vitalícia para garantir que os valores sejam "emprestados" e movidos de maneira previsível e explícita.

O seguinte demonstra como alguém pode passar um fechamento como um parâmetro de entrada usando o Fntrait:

// A function that takes a value of type F (which is defined as
// a generic type that implements the `Fn` trait, e.g. a closure)
// and calls it with the value `5`.
fn apply_by_ref<F>(f: F) -> i32
    where F: Fn(i32) -> i32
{
    f(5)
}

fn main() {
    let f = |x| {
        println!("I got the value: {}", x);
        x * 2
    };
    
    // Applies the function before printing its return value
    println!("5 * 2 = {}", apply_by_ref(f));
}

// ~~ Program output ~~
// I got the value: 5
// 5 * 2 = 10

Scala

No Scala , as funções anônimas usam a seguinte sintaxe:

(x: Int, y: Int) => x + y

Em certos contextos, como quando uma função anônima é um parâmetro que está sendo passado para outra função, o compilador pode inferir os tipos dos parâmetros da função anônima e eles podem ser omitidos na sintaxe. Em tais contextos, também é possível usar uma abreviação para funções anônimas usando o caractere de sublinhado para introduzir parâmetros não nomeados.

val list = List(1, 2, 3, 4)
list.reduceLeft( (x, y) => x + y ) 
// Here, the compiler can infer that the types of x and y are both Int. 
// Thus, it needs no type annotations on the parameters of the anonymous function.

list.reduceLeft( _ + _ )   
// Each underscore stands for a new unnamed parameter in the anonymous function. 
// This results in an even shorter equivalent to the anonymous function above.

Conversa fiada

Em Smalltalk, as funções anônimas são chamadas de blocos e são invocadas (chamadas) enviando-lhes uma mensagem de "valor". Se os argumentos devem ser passados, uma mensagem "valor: ... valor:" com um número correspondente de argumentos de valor deve ser usada.

Por exemplo, no GNU Smalltalk ,

st> f:=[:x|x*x]. f value: 8 .
64
st> [:x :y|x+y] value: 5 value: 6 .
11

Os blocos Smalltalk são tecnicamente encerramentos, permitindo que eles sobrevivam ao seu escopo de definição e ainda se refiram às variáveis ​​declaradas neles.

st> f := [:a|[:n|a+n]] value: 100 .
a BlockClosure
"returns the inner block, which adds 100 (captured in "a" variable) to its argument."
st> f value: 1 .
101
st> f value: 2 .
102

Rápido

Em Swift , as funções anônimas são chamadas de encerramentos. A sintaxe tem a seguinte forma:

{ (parameters) -> returnType in
  statement
}

Por exemplo:

{ (s1: String, s2: String) -> Bool in
  return s1 > s2
}

Para fins de brevidade e expressividade, os tipos de parâmetro e tipo de retorno podem ser omitidos se puderem ser inferidos:

{ s1, s2 in return s1 > s2 }

Da mesma forma, o Swift também oferece suporte a instruções de retorno implícitas para encerramentos de uma instrução:

{ s1, s2 in s1 > s2 }

Finalmente, os nomes dos parâmetros também podem ser omitidos; quando omitidos, os parâmetros são referenciados usando nomes de argumentos abreviados, consistindo no símbolo $ seguido por sua posição (por exemplo, $ 0, $ 1, $ 2, etc.):

{ $0 > $1 }

Tcl

Em Tcl , a aplicação da função de quadratura anônima a 2 tem a seguinte aparência:

apply {x {expr {$x*$x}}} 2
# returns 4

Este exemplo envolve dois candidatos para o que significa ser uma função em Tcl. O mais genérico é geralmente chamado de prefixo de comando , e se a variável f contém tal função, então a maneira de executar a aplicação da função f ( x ) seria

{*}$f $x

onde {*}está o prefixo de expansão (novo no Tcl 8.5). O prefixo do comando no exemplo acima é aplicar. Os {x {expr {$x*$x}}} nomes dos comandos podem ser associados aos prefixos do comando por meio do interp aliascomando. Os prefixos de comando suportam currying . Os prefixos de comando são muito comuns em APIs Tcl .

O outro candidato a "função" em Tcl é geralmente chamado de lambda e aparece como {x {expr {$x*$x}}}parte do exemplo acima. Esta é a parte que armazena em cache a forma compilada da função anônima, mas só pode ser chamada sendo passada para o applycomando. Lambdas não suportam currying, a menos que emparelhado com um applypara formar um prefixo de comando. Lambdas são raros em APIs Tcl.

Vala

No Vala , funções anônimas são suportadas como expressões lambda.

delegate int IntOp (int x, int y);

void main () {
	IntOp foo = (x, y) => x * y;
	stdout.printf("%d\n", foo(10,5));
}

Visual Basic .NET

O Visual Basic .NET 2008 introduziu funções anônimas por meio da forma lambda. Combinado com a digitação implícita, o VB fornece uma sintaxe econômica para funções anônimas. Como no Python, no VB.NET, as funções anônimas devem ser definidas em uma linha; eles não podem ser declarações compostas. Além disso, uma função anônima em VB.NET deve ser verdadeiramente um VB.NET Function- deve retornar um valor.

Dim foo = Function(x) x * x
Console.WriteLine(foo(10))

Visual Basic.NET 2010 adicionou suporte para expressões lambda multilinhas e funções anônimas sem um valor de retorno. Por exemplo, uma função para uso em um Thread.

Dim t As New System.Threading.Thread(Sub ()
                                         For n As Integer = 0 To 10   'Count to 10
                                             Console.WriteLine(n)     'Print each number
                                         Next
                                     End Sub
                                     )
t.Start()

Veja também

Referências

links externos