Função anônima

Da Wikipédia, a enciclopédia livre
Ir para navegação Pular para pesquisar

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 são frequentemente 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. [1] 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. As 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. [2] Em várias linguagens de programação, funções anônimas são introduzidas usando a palavra-chave lambda , e 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 oferece suporte a 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 é qualquer 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 . [3]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, as funções anônimas são comumente implementadas para fins 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 um nome mais genérico função.

Os exemplos a seguir foram escritos em Python 3.

Classificando

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  =  [ 'casa' ,  'carro' ,  'bicicleta' ] 
>>>  a . sort ( key = lambda  x :  len ( x )) 
>>>  a 
[ 'carro' ,  'bicicleta' ,  'casa' ]

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 ,  ... :  < operação  nos argumentos que retornam um valor >     

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 ,  'número' ,  11,2 ] 
>>>  a . sort ( chave = lambda  x :  x . __class__ . __name__ ) 
>>>  a 
[ 11,2 ,  10 ,  'número' ]

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 ( limite ): 
    retornar  lambda  x :  x  <  limite

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.

Currying

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 ): 
...      retorna  x  /  y

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

>>>  metade  =  divisor ( 2 ) 
>>>  terceiro  =  divisor ( 3 )

>>>  imprimir ( meio ( 32 ),  terceiro ( 32 )) 
16,0  10.666666666666666

>>>  imprimir ( metade ( 40 ),  terceiro ( 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 ] 
>>>  lista ( mapa ( 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  para  x  em  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 ] 
>>>  lista ( filtro ( 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  para  x  em  a  se  x  %  2  ==  0 ] 
[ 2 ,  4 ,  6 ]

Dobre

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:

>>>  das  funções de  importação  reduzir 
>>>  a  =  [ 1 ,  2 ,  3 ,  4 ,  5 ] 
>>>  reduzir ( 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 dobra. 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 idiomas

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 as 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 tipos de dados.

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 feita para suportar funções anônimas no Bash. [4]
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 [5]
C ++ Carrapato verdeY A partir do padrão C ++ 11
CFML Carrapato verdeY A partir de Railo 4, [6] ColdFusion 10 [7]
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. [8]
Ondulação Carrapato verdeY
D Carrapato verdeY
Dardo Carrapato verdeY [9]
Delphi Carrapato verdeY [10]
Dylan Carrapato verdeY
Eiffel Carrapato verdeY
Olmo Carrapato verdeY
Elixir Carrapato verdeY [11]
Erlang Carrapato verdeY [12]
F # Carrapato verdeY [13]
Excel Carrapato verdeY Função de planilha do Excel, versão beta 2021 [14]
Fator Carrapato verdeY "Cotações" apóiam isso [15]
Fortran X vermelhoN
Frink Carrapato verdeY [16]
Ir Carrapato verdeY [17]
Gosu Carrapato verdeY [18]
Groovy Carrapato verdeY [19]
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 [20]
Kotlin Carrapato verdeY [21]
Lisp Carrapato verdeY
Logtalk Carrapato verdeY
Lua Carrapato verdeY [22]
CAXUMBA X vermelhoN
Mathematica Carrapato verdeY
Bordo Carrapato verdeY [23]
MATLAB Carrapato verdeY
Maxima Carrapato verdeY [24]
Shell de próxima geração Carrapato verdeY
Nim Carrapato verdeY [25]
OCaml Carrapato verdeY [26]
Oitava Carrapato verdeY [27]
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. [28]
Pascal X vermelhoN
Perl Carrapato verdeY [29]
PHP Carrapato verdeY A partir do PHP 5.3.0, funções anônimas verdadeiras são suportadas. [30] 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 suporta funções anônimas por meio da sintaxe lambda, [31] que suporta apenas expressões, não instruções.
R Carrapato verdeY
Raquete Carrapato verdeY [32]
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 [33]
Vala Carrapato verdeY [33]
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 { × }  ⍝ Como a dfn 
      f  1  2  3 
1  4  9      
      g ⊢ × ⊢    ⍝ Como um trem 3 tácito (bifurcação) 
      g  1  2  3 
1  4  9 
      h ×     ⍝ Como uma função tácita derivada 
      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  ( parâmetros )  {  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, usar __typeof__on array retornaria testtype *, que pode ser desreferenciado para o valor real, se necessário.

#include  <stdio.h>

// * esta é a definição da função anônima * / 
#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 ; 
  para  (  i  =  0 ;  i  <  3 ;  ++  i  ) 
    printf ( "% d% d \ n " ,  matriz [ i ]. a ,  matriz [ i ]. b ); 
  printf ( " \ n " ); 
}

int  principal ( vazio ) 
{ 
  TestType  matriz []  =  {  { 0 , 1 },  { 2 , 3 },  { 4 , 5 }  };

  impressão ( matriz ); 
  / * a função anônima é fornecida como função para foreach * / 
  forEachInArray ( testtype ,  array , 
    lambda  ( testtype ,  ( void  * item ), 
    { 
      int  temp  =  ( * (  testtype  * )  item ). a ; 
      ( * (  testtype  * )  item ). a  =  ( * (tipo de  teste  * ) item ). b ; 
      ( * (  testtype  * )  item ). b  =  temp ; 
      return  ( * (  testtype  * )  item ); 
    })); 
  impressão ( matriz ); 
  return  0 ; 
}

Tinido (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  (  parâmetros  )  {  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 " ); 
  };

/ * Passar como parâmetro para outra função * / 
  dispatch_async ( dispatch_get_global_queue ( DISPATCH_QUEUE_PRIORITY_DEFAULT ,  0 ),  count_loop );

/ * 
  Chama diretamente * / 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:

[ captura ] ( parâmetros )  ->  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:

[]         // Sem capturas, o lambda é implicitamente conversível em um ponteiro de função. 
[ x ,  & y ]    // x é capturado pelo valor ey é capturado por referência. 
[ & ]        // Qualquer variável externa é capturada implicitamente por referência se usada 
[ = ]        // Qualquer variável externa é capturada implicitamente por valor, se usada. 
[ & ,  x ]     // x é capturado pelo valor. Outras variáveis ​​serão capturadas por referência. 
[ = ,  & z ]    // z é capturado por referência. Outras variáveis ​​serão capturadas por valor.

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 >  alguma_lista {  1 ,  2 ,  3 ,  4 ,  5  }; 
total int  = 0 ; std :: for_each ( begin ( some_list ), end ( some_list ), [ & total ] ( int x ) { total + = x ; }); // Observe que std :: acumular seria uma alternativa muito melhor aqui ...  
  
                	    

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 >  alguma_lista {  1 ,  2 ,  3 ,  4 ,  5  }; 
total int  = 0 ; valor int = 5 ; std :: for_each ( begin ( some_list ), end ( some_list ), [ & total , value , this ] ( int x ) { total + = x  
   
  
                     *  valor  *  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 é 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>

 eval duplo ( std :: função < double ( double ) >  f ,  double  x  =  2,0 )  { 
  return  f ( x ); 
}

int  main ()  { 
  std :: function < double ( double ) >  f0  =  [] ( double  x )  {  return  1 ;  }; 
  auto  f1  =  [] ( duplo  x )  {  retorno  x ;  }; 
  decltype ( f0 )  fa [ 3 ]  =  { f0 ,  f1 ,  [] ( duplo  x )  { return  x  *  x ;  }}; 
  std :: vetor < decltype ( f0 ) >  fv  =  { f0 ,  f1 }; 
  fv . push_back ([] ( double  x )  {  return  x  *  x ;  }); 
  para  ( size_t  i  =  0 ;  i  <  fv . size ();  i ++ )  { 
    std :: cout <<  fv [ i ] ( 2.0 )  <<  std :: endl ; 
  } 
  para  ( size_t  i  =  0 ;  i  <  3 ;  i ++ )  { 
    std :: cout  <<  fa [ i ] ( 2.0 )  <<  std :: endl ; 
  } 
  para  ( auto &  f  :  fv )  { 
    std :: cout  << f ( 2.0 )  <<  std :: endl ; 
  } 
  para  ( 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 );  // chama o lambda.

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

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 . [35]

// o primeiro int é o tipo x ' 
// o segundo int é o tipo de retorno 
// <consulte 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:

// NÃO irá compilar! 
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):

// Inicialize a lista: 
var  values  =  new  List < int > ()  {  7 ,  13 ,  4 ,  9 ,  3  }; 
// Mapeie a função anônima sobre todos os elementos da lista, retorne a nova lista 
var  foo  =  values . ConvertAll ( d  =>  d  *  d )  ;  
// o resultado da variável foo é do tipo 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 ); 
        estático  int  Square ( int  d ) 
        { 
            return  d  *  d ; 
        }
 
        static  void  Main ( string []  args ) 
        { 
            // C # 1.0: sintaxe do delegado original necessária 
            // inicializando com um método nomeado. 
            SquareDelegate  A  =  novo  SquareDelegate ( Square ); 
            Sistema . Console . WriteLine ( A ( 3 ));
 
            // C # 2.0: Um delegado pode ser inicializado com 
            // código embutido, chamado de "método anônimo". Este 
            // método usa um int como parâmetro de entrada. 
            SquareDelegate  B  =  delegado ( int  d )  {  return  d  *  d ;  }; 
            Sistema . Console . WriteLine ( B ( 5 ));
 
            // C # 3.0. Um delegado pode ser inicializado com 
            // uma expressão lambda. O lambda recebe um int e retorna um int. 
            // O tipo de x é inferido pelo compilador. 
            SquareDelegate  C  =  x  =>  x  *  x ; 
            Sistema . Console . WriteLine ( C ( 7 ));
 
            // C # 3.0. Um delegado que aceita uma entrada e 
            // retorna uma saída também pode ser declarado implicitamente com o tipo Func <>. 
            Sistema . Func < int , int >  D  =  x  =>  x  *  x ; 
            Sistema . 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 () { 
  // instruções 
};

Ou usando uma função de seta:

fn  =  ()  =>  { 
  // instruções 
};

fn  =  ()  =>  singleExpression  // singleExpression é retornado implicitamente. Não há necessidade de colchetes ou a palavra-chave de retorno

fn  =  singleParam  =>  {  // se a função de seta tiver apenas um parâmetro, não há necessidade de parênteses 
    // instruções 
}

fn  =  ( x ,  y )  =>  {  // se a função de seta tem zero ou vários parâmetros, é necessário usar parênteses 
    // instruções 
}

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:

fatorial  =  função ( n ) { 
    retorno  n  >  1  ?  n  *  fatorial ( 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 ( argumentos ) { / * body * / }

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

( x ) { return  x * x ;} 
delegado  ( x ) { return  x * x ;}  // se mais verbosidade é necessária 
( int  x ) { return  x * x ;}  // se o tipo de parâmetro não pode ser inferido 
delegado  ( int  x ) { return  x * x ;}  // idem 
delegado  double ( int  x ) { return  x * x ;} // se o tipo de retorno deve ser forçado manualmente

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  =  ( duplo  x ) { return  x * x ;}; 
duplo  y  =  sqr ( 4 );

Dart

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

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

ou

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

Delphi

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

 demonstração do programa ;

tipo 
  TSimpleProcedure  =  referência  ao  procedimento ; 
  TSimpleFunction  =  referência  à  função ( const  x :  string ) :  Integer ;

var 
  x1 :  TSimpleProcedure ; 
  y1 :  TSimpleFunction ;

begin 
  x1  : =  procedure 
    begin 
      Writeln ( 'Hello World' ) ; 
    fim ; 
  x1 ;    // invoca o método anônimo recém-definido

  y1  : =  função ( const  x :  string ) :  Inteiro 
    começar 
      Resultado  : =  Comprimento ( x ) ; 
    fim ; 
  Writeln ( y1 ( 'bar' )) ;  
fim .

PascalABC.NET

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

começar 
  var  n  : =  10000000 ; 
  var  pp  : =  intervalo ( 1 , n ) 
    . Selecione ( x -> Rec ( Random () , Random ())) 
    . Onde ( p -> sqr ( p . Item1 ) + sqr ( p . Item2 ) < 1 ) 
    . Contagem / n * 4 ; 
  Impressão( pp ) ; 
fim .

Elixir

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

soma  =  fn ( a ,  b )  ->  a  +  b  soma final 
. ( 4 , 3 ) # => 7 


quadrado  =  fn ( x )  ->  x  *  x  final 
Enum . mapa  [ 1 ,  2 ,  3 ,  4 ],  quadrado 
# => [1, 4, 9, 16]

Erlang

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

% Função anônima vinculada à variável 
Square Square  =  fun ( X )  ->  X  *  X  end .

Função denominada% com a mesma funcionalidade 
quadrado ( X )  ->  X  *  X .

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

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 ao mecanismo de inferência de tipo e suportam toda a sintaxe e recursos das funções "comuns" (exceto para o uso de múltiplas 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 ]  - retorna [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  =  função ( x )  return  x * x ; 
f ( 8 );  // 64

( função ( x , y )  retorna  x + y ) ( 5 , 6 );  // 11

Java

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

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. [37]

// sem parâmetro 
()  ->  Sistema . para fora . println ( "Olá, mundo." )

// com um parâmetro (este exemplo é uma função de identidade). 
a  ->  a

// com uma expressão 
( a ,  b )  ->  a  +  b

// com informações de tipo explícito 
( id longo  , nome da string ) -> "id:" + id + ", nome:" + nome          

// com um bloco de código 
( a ,  b )  ->  {  return  a  +  b ;  }

// com várias instruções no corpo lambda. Ele precisa de um bloco de código. 
// Este exemplo também inclui duas expressões lambda aninhadas (a primeira também é um encerramento). 
( id ,  preço padrão )  ->  { 
    Opcional < Produto >  product  =  productList . stream (). filtro ( p  ->  p . getId ()  ==  id ). findFirst (); 
    produto de retorno  . 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), [37] como no exemplo a seguir:

público  classe  Calculator  { 
    interface de  IntegerMath  { 
        int  operação ( int  a ,  int  b );

        padrão  IntegerMath  swap ()  { 
            return  ( a ,  b )  ->  operação ( b ,  a ); 
        } 
    }

    private  static  int  aplicar ( int  a ,  int  b ,  IntegerMath  op )  { 
        return  op . operação ( a ,  b ); 
    }

    public  static  void  main ( String ...  args )  { 
        IntegerMath  adição  =  ( a ,  b )  ->  a  +  b ; 
        Subtração IntegerMath  = ( a , b ) -> a - b ; Sistema . para fora . println ( "40 + 2 =" + aplicar ( 40 , 2 , adição )); Sistema       
            
        . para fora . println ( "20 - 10 ="  +  aplicar ( 20 ,  10 ,  subtração )); 
        Sistema . para fora . println ( "10 - 20 ="  +  aplicar ( 20 ,  10 ,  subtração . trocar ()));     
    } 
}

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 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 sofrer mutação dentro ou fora do escopo lambda.

JavaScript

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

alert (( função ( 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:

alerta (( 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 . título = localização . 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 . título = localização . 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:

( função () {  ...  } ())

e

( função () {  ...  }) ()

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 porque as ligações globais estão comprometidas), uma sequência arbitrária de instruções JavaScript com chaves {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 que se seguem:

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

( função  ( lambda  ( arg )  ( faça algo  arg )))

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

; usando aspas acentuadas 
# ' ( lambda  ( arg )  ( do-something  arg )) 
; usando a macro lambda: 
( 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 no Common Lisp também podem receber nomes globais posteriormente:

( setf  ( símbolo-função  'sqr ) 
      ( lambda  ( x )  ( *  x  x ))) 
; o que nos permite chamá-lo usando o nome 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

( defina 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 )  ; Define uma função anônima que pega três argumentos e os soma.

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

( função defn  [arg] ( + 3 arg ))    

expande para:

( função def  ( 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. [38]

Assim, em Lua

função  foo ( x )  retorna  2 * x  fim

é apenas açúcar sintático para

foo  =  função ( x )  retorna  2 * x  fim

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

table.sort ( rede ,  função ( a , b ) 
  retorna  a . nome  >  b . nome 
fim )

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 &
     Função [ x , x + 1 ]
     x \ [ Função ] x + 1  

Então, por exemplo:

    f : = # 1 ^ 2 & ; f [ 8 ] 
     64
    # 1 + # 2 e [ 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:

     Se [ # 1 == 1 , 1 , # 1 * # 0 [ # 1 -1 ]] e      

Por exemplo, 6 fatorial seria:

     Se [ # 1 == 1 , 1 , # 1 * # 0 [ # 1 -1 ]] e [ 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 capturadas por valor.

>> f = @ ( x ) x * x ; f ( 8 )    
ans = 64   
>> (@ ( x , y ) x + y ) ( 5 , 6 ) % Funciona apenas no 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:

diversão  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. [39]

F #

F # suporta funções anônimas, [13] da seguinte maneira:

( diversão  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

Next Generation Shell

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 )                        # Resultado: 64 
f  =  {  A * B + C  };  f ( 2 , 3 , 4 )              # Resultado: 10 
f  =  F ( x : Int ,  y : Int )  x * y + 2 ;  f ( 3 ,  4 )   # Resultado: 14

f  =  "$ {X} tem tudo a ver com $ {Y}" 
f ( "programação" ,  "semântica" )        # Resultado: "programação tem tudo a ver com semântica"

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

[ 0 , 1 , 2 ]. mapa ( X * 2 )                     # Resultado: [0,2,4]

dados  =  { "a" :  "xxx" ,  "b" :  "yyy" } 
dados . map ( "$ {X} é $ {Y}" )             # Resultado: ["a é xxx", "b é yyy"]

Nim

O Nim oferece suporte a funções anônimas de múltiplas linhas de múltiplas linhas. [25]

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

Exemplo de várias linhas:

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

afirmar  anon ( 9 )

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

var  cities  =  @ [ "Frankfurt" ,  "Tóquio" ,  "Nova York" ]

cidades . 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 suporta funções anônimas, [29] como segue:

( sub  {  print  "Fui chamado \ n"  }) -> ();          # 1. totalmente anônimo, chamado como criado

meu  $ quadrado  =  sub  {  meu  $ x  =  deslocamento ;  $ x  *  $ x  };  # 2. atribuído a uma variável

sub  curry  { 
    my  ( $ sub ,  @args )  =  @_ ; 
    return  sub  {  $ sub -> ( @args ,  @_ )  };          # 3. como um valor de retorno de outra função 
}

# exemplo de currying em 
sub  sum de  programação Perl {  my  $ tot  =  0 ;  $ tot  + =  $ _  para  @_ ;  $ tot  }  # retorna a soma de seus argumentos 
my  $ curried  =  curry  \ & sum ,  5 ,  7 ,  9 ; 
imprimir  $ curried -> ( 1 , 2 , 3 ),  "\ n" ;     # imprime 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.

meu  @squares  =  map  {  $ _  *  $ _  }  1 .. 10 ;    # map e grep não usam a palavra-chave 'sub' 
my  @ square2  =  map  $ _  *  $ _ ,  1 .. 10 ;       # chaves desnecessárias para uma expressão

meu  @bad_example  =  map  {  imprimir  para  @_  }  1 .. 10 ;  # valores não passados ​​como função Perl normal

PHP

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

PHP 4.0.1 para 5,3

PHP 4.0.1 introduziu o create_functionque era o suporte inicial de função anônima. 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. [41]

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

Neste exemplo, $funcé uma instância de Closuree echo $func($x)é equivalente a echo $func->__invoke($x). O PHP 5.3 imita funções anônimas, mas não suporta funções anônimas verdadeiras porque as funções do 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 ;  // imprime 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 );  // imprime 6

Dialetos do Prolog

Logtalk

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

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

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

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

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

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

Visual Prolog

Funções anônimas (em geral predicados anônimos ) foram introduzidas no Visual Prolog na versão 7.2. [42] 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:

cláusulas 
    mkAdder ( X )  =  {  ( Y )  =  X + Y  }.

Python

Python suporta funções anônimas simples por meio da forma lambda. [31] 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  <-  função ( x ) x * x ;  f ( 8 ) 
[1] 64 
> ( função ( 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
    { diga  "fui chamado" };
    
  2. atribuído a uma variável
    meu  $ squarer1 = -> $ x { $ x * $ x };             # 2a. bloco pontiagudo 
    meu  $ squarer2 = { $ ^ x * $ ^ x };                 # 2b. twigil 
    my  $ squarer3 = { my  $ x = shift  @_ ; $ x * $ x }; # 2c. Estilo Perl 5
    
  3. escovando
    sub  add ( $ m , $ n ) { $ m + $ n }
     meu  $ sete    = add ( 3 , 4 );
    meu  $ add_one = & add . assumindo ( m => 1);
    meus $ oito =  $ add_one ( $ sete );
    
  4. Objeto WhateverCode
    meu  $ w = * - 1 ;       # Objeto WhateverCode 
    meu  $ b = { $ _ - 1 };  # mesma funcionalidade, mas como bloco chamável
    

Ruby

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. [43] Quando passado para um método, um bloco é convertido em um Proc em algumas circunstâncias.

irb (main): 001: 0> # Exemplo 1: 
irb (main): 002: 0 * # Funções puramente anônimas usando blocos. 
irb (principal): 003: 0 * ex  =  [ 16 . 2 ,  24 . 1 ,  48 . 3 ,  32 . 4 ,  8 . 5 ] 
=> [16,2, 24,1, 48,3, 32,4, 8,5] 
irb (principal): 004: 0> ex . sort_by  {  | x |  x  -  x . to_i  }  # Classifica pela parte fracionária, ignorando a parte inteira.
=> [24,1, 16,2, 48,3, 32,4, 8,5] 
irb (principal): 005: 0> # Exemplo 2: 
irb (principal): 006: 0 * # Funções de primeira classe como um objeto explícito de Proc - 
irb (principal ): 007: 0 * ex  =  Proc . new  {  puts  "Hello, world!"  } 
=> # <Proc: 0x007ff4598705a0 @ (irb): 7> 
irb (principal): 008: 0> ex . ligue para 
Olá, mundo! 
=> nil 
irb (main): 009: 0> # Exemplo 3: 
irb (main): 010: 0 * # Função que retorna o objeto de função lambda com parâmetros 
irb (main): 011: 0 * def  is_multiple_of ( n ) 
irb ( principal): 012: 1>  lambda { | x |  x  %  n  ==  0 } 
irb (principal): 013: 1> end 
=> nil 
irb (principal): 014: 0> multiple_four  =  is_multiple_of ( 4 ) 
=> # <Proc: 0x007ff458b45f88 @ (irb): 12 (lambda )> 
irb (principal): 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. [44] Eles são definidos usando a seguinte sintaxe:

| < parâmetro - nome > : < tipo > |  -> < return - type > { < body > };   

Por exemplo:

deixe 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:

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

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

deixe f = | x | x * 2 ;      

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

deixe f = || println! ( "Olá, mundo!" );    

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

// Uma função que recebe um ponteiro de função como argumento e o chama com 
// o valor `5`. 
fn  apply ( f : fn ( i32 )  -> i32 )  -> i32  {
    // Sem ponto e vírgula para indicar um retorno implícito 
f ( 5 )    
}

fn  main () { 
    // Definindo o fechamento 
seja f = | x | x * 2 ;          

    println! ( "{}" , aplique ( 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: [45]

  • 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. [45] Eles ajudam a controlar como os valores são movidos entre os escopos, o que é muito importante, já que Rust segue uma construção vitalícia para garantir que os valores sejam "emprestados" e movidos de maneira previsível e explícita. [46]

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

// Uma função que recebe um valor do tipo F (que é definido como 
// um tipo genérico que implementa a característica `Fn`, por exemplo, um fechamento) 
// e o chama com o 
valor` 5`. fn  apply_by_ref < F > ( f : F )  -> i32 
    onde F : Fn ( i32 ) -> i32 {  

    f ( 5 )
}

fn  main () { 
    deixe f = | x | {    
        println! ( "Recebi o valor: {}" , x ); 
        x * 2  
    };
    
    // Aplica a função antes de imprimir seu valor de retorno 
println! ( "5 * 2 = {}" , apply_by_ref ( f ));     
}

// ~~ Saída do programa ~~ 
// Recebi o valor: 5 
// 5 * 2 = 10

Scala

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

( 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  lista  =  Lista ( 1 ,  2 ,  3 ,  4 ) 
lista . reduzLeft (  ( x ,  y )  =>  x  +  y  )  
// Aqui, o compilador pode inferir que os tipos de xey são ambos Int. 
// Assim, ele não precisa de anotações de tipo nos parâmetros da função anônima.

lista . reduzLeft (  _  +  _  )    
// Cada sublinhado representa um novo parâmetro sem nome na função anônima. 
// Isso resulta em um equivalente ainda mais curto para a função anônima acima.

Smalltalk

Em Smalltalk, 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.

[ : x  |  x * x ] valor:  4 
"retorna 16"

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.

[ : a  | 
    [ : n  |  a  +  n ]
] valor:  10 
"retorna o bloco interno, que adiciona 10 ao seu argumento."

Swift

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

{  ( parâmetros )  ->  returnType  na 
  instrução 
}

Por exemplo:

{  ( s1 :  String ,  s2 :  String )  ->  Bool  no 
  retorno  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  no  retorno  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  em  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 é a seguinte: [49]

aplicar  { x  {expr  { $ x * $ x }}}  2 
# retorna 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 é apply. 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 para "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 ela 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. [50]

delegar  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  =  Função ( x )  x  *  x 
Console . WriteLine ( foo ( 10 ))

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

Dim  t  como  novo  sistema . Threading . Tópico ( Sub  () 
                                         Para  n  Como  Integer  =  0  Para  10    'Conte até 10 
                                             Console . WriteLine ( n )      ' Imprimir cada número 
                                         Seguinte 
                                     End  Sub 
                                     ) 
t . Iniciar ()

Veja também

Referências

  1. ^ "Funções de ordem superior" . learnyouahaskell.com . Retirado em 3 de dezembro de 2014 .
  2. ^ Fernandez, Maribel (2009), Modelos de Computação: Uma Introdução à Teoria da Computabilidade , Tópicos de Graduação em Ciência da Computação, Springer Science & Business Media, p. 33, ISBN 9781848824348, O cálculo Lambda ... foi introduzido por Alonzo Church na década de 1930 como uma notação precisa para uma teoria de funções anônimas
  3. ^ "Expressões de função de seta - JavaScript" . MDN .
  4. ^ "Bash lambda" . 08/03/2019.
  5. ^ BillWagner. "Expressões lambda - referência C #" . docs.microsoft.com . Obtido em 2020-11-24 .
  6. ^ "Suporte de fechamento" . Arquivado do original em 06/01/2014 . Recuperado em 05-01-2014 .
  7. ^ "O que há de novo no ColdFusion 10" . Arquivado do original em 06/01/2014 . Recuperado em 05-01-2014 .
  8. ^ "Referência COBOL gerenciada" . Documentação da Micro Focus . Micro Focus . Retirado em 25 de fevereiro de 2014 .
  9. ^ a b "Um passeio pela linguagem Dart" . dart.dev . Obtido em 2020-11-24 .
  10. ^ "Métodos Anônimos em Delphi - RAD Studio" . docwiki.embarcadero.com . Obtido em 2020-11-24 .
  11. ^ a b "Sintaxe de Erlang / Elixir: Um curso intensivo" . elixir-lang.github.com . Obtido em 2020-11-24 .
  12. ^ a b "Erlang - Funs" . erlang.org . Obtido em 2020-11-24 .
  13. ^ a b cartermp. "Expressões lambda: a palavra-chave divertida - F #" . docs.microsoft.com . Obtido em 2020-11-24 .
  14. ^ "LAMBDA: A função definitiva de planilha do Excel" . microsoft.com . Recuperado em 2021-03-30 .
  15. ^ "Citações - Fator Documentação" . Retirado em 26 de dezembro de 2015 . Uma cotação é uma função anônima (um valor que denota um fragmento de código) que pode ser usada como um valor e chamada usando os combinadores fundamentais.
  16. ^ "Frink" . frinklang.org . Obtido em 2020-11-24 .
  17. ^ a b "Funções anônimas em GoLang" . GoLang Docs . Obtido em 2020-11-24 .
  18. ^ "Documentação Gosu" (PDF) . Retirado em 4 de março de 2013 .
  19. ^ "Documentação Groovy" . Arquivado do original em 22 de maio de 2012 . Retirado em 29 de maio de 2012 .
  20. ^ "Funções · A linguagem Julia" . docs.julialang.org . Obtido em 2020-11-24 .
  21. ^ "Funções de ordem superior e Lambdas - linguagem de programação Kotlin" . Kotlin . Obtido em 2020-11-24 .
  22. ^ "Programação em Lua: 6" . www.lua.org . Obtido em 2020-11-24 .
  23. ^ "Programação Maple: 1.6: Funções e expressões anônimas - Application Center" . www.maplesoft.com . Obtido em 2020-11-24 .
  24. ^ "Maxima 5.17.1 Manual: 39. Definição de Função" . maths.cnam.fr . Obtido em 2020-11-24 .
  25. ^ a b "Manual Nim" . nim-lang.github.io .
  26. ^ "Exemplos de código - OCaml" . ocaml.org . Obtido em 2020-11-24 .
  27. ^ "GNU Octave: funções anônimas" . octave.org . Obtido em 2020-11-24 .
  28. ^ "Literais de função" . Manual do usuário do OpenSCAD . Wikilivros . Página visitada em 22 de fevereiro de 2021 .
  29. ^ a b "perlsub - sub-rotinas Perl - Navegador Perldoc" . perldoc.perl.org . Obtido em 2020-11-24 .
  30. ^ "PHP: Funções anônimas - Manual" . www.php.net . Obtido em 2020-11-24 .
  31. ^ a b "6. Expressões - documentação do Python 3.9.0" . docs.python.org . Obtido em 2020-11-24 .
  32. ^ "4.4 Funções: lambda" . docs.racket-lang.org . Obtido em 2020-11-24 .
  33. ^ a b "Projetos / Vala / Tutorial - GNOME Wiki!" . wiki.gnome.org . Obtido em 2020-11-24 .
  34. ^ Järvi, Jaakko; Powell, Gary (nd). "Capítulo 16. Boost.Lambda" . Boost Documentation . Boost . Recuperado em 22 de dezembro de 2014 .
  35. ^ "Especificação de linguagem C # 5.0" . Centro de Download da Microsoft .
  36. ^ "O que há de novo no JDK 8" .
  37. ^ a b Os tutoriais Java: Expressões Lambda , docs.oracle.com
  38. ^ "Programação em Lua - Mais sobre funções" . Arquivado do original em 14 de maio de 2008 . Página visitada em 2008-04-25 .
  39. ^ "2.7. Funções anônimas · GitBook" . www.cs.cornell.edu .
  40. ^ http://php.net/create_function no topo da página indica isso com "(PHP 4> = 4.0.1, PHP 5)"
  41. ^ "PHP: rfc: closures" . wiki.php.net .
  42. ^ "Predicados anônimos" . em Visual Prolog Language Reference
  43. ^ Sosinski, Robert (2008-12-21). "Entendendo Blocos Ruby, Procs e Lambdas" . Reactive.IO. Arquivado do original em 31/05/2014 . Página visitada em 30/05/2014 .
  44. ^ "Closures - Rust By Example" . doc.rust-lang.org .
  45. ^ a b "Como parâmetros de entrada - Rust By Example" . doc.rust-lang.org .
  46. ^ "Lifetimes - Rust By Example" . doc.rust-lang.org .
  47. ^ "Sintaxe de função anônima - Documentação Scala" . Arquivado do original em 23/07/2013 . Página visitada em 31-12-2010 .
  48. ^ "Fechamentos - A linguagem de programação Swift (Swift 5.5)" . docs.swift.org .
  49. ^ aplique a página do manual , recuperada em 06/09/2012.
  50. ^ Vala Reference Manual , recuperado em 2021-06-09.

Ligações externas