Funcție anonimă

De la Wikipedia, enciclopedia liberă.
Salt la navigare Salt la căutare

În programarea computerului , o funcție anonimă sau o funcție lambda este o funcție definită și posibil numită, fără a fi legată de un identificator. Funcțiile anonime sunt utile pentru trecerea unei funcții de ordin superior ca argument și se găsesc în limbi care acceptă funcții de primă clasă, cum ar fi Haskell .

Funcțiile anonime sunt o formă de funcție imbricată, care permite accesul la variabile din sfera funcției care conține (variabile nelocale). Deși sunt denumite funcții imbricate, ele nu pot fi recursive fără ajutorul unui operator combinator de punct fix care în acest caz se numește punct fix fix sau recursivitate anonimă .

Aceste funcții anonime provin din lucrarea Bisericii Alonzo asupra calculului Lambda din 1936 . În multe limbaje de programare, funcțiile anonime sunt introduse cu cuvântul cheie lambda și de aceea sunt denumite funcții lambda.

Încă din 1958 , Lisp avea funcții anonime. Astăzi se găsesc în multe alte limbi, cum ar fi Scala , JavaScript , Ruby , Python , PHP , C ++ , Perl , Visual Basic , Delphi , Java etc., deși unele dintre acestea nu au originea ca limbaje funcționale .

Suport în diferite limbi

Piton

Python acceptă funcții anonime simple prin formularul lambda. Corpul de execuție lambda trebuie să fie o expresie și nu o declarație, deci aceasta este o restricție asupra utilității sale. Valoarea returnată de lambda este valoarea conținută în expresie.

 foo = lambda x : x * x
print ( foo ( 10 ))

VB.NET

În Visual Basic.NET, puteți crea funcții anonime sau lambda folosind cuvintele cheie Sub sau Funcție în același mod în care creați un subrutină sau o funcție normală. Expresiile Lambda sunt incluse într-o declarație (care poate avea totuși mai multe linii). Puteți crea expresii lambda care utilizează procesare asincronă utilizând operatorii Async și Await .

 Dim sum = Funcție ( x )
               Returnează x + 2
            Funcția de sfârșit

Rubin

Ruby acceptă funcții anonime folosind o structură sintactică numită bloc . Când este trecut la o metodă, un bloc este convertit într-un obiect de clasă Proc în anumite circumstanțe.

 # Exemplul 1:
# Funcții pur anonime folosind blocuri.
ex = [ 16 . 2 , 24 . 1 , 48 . 3 , 32 . 4 , 8 . 5 ]
ex . sort_by { | x | x - x . to_i } # sortează după partea fracționată, ignorând partea întreagă.
# [24.1, 16.2, 48.3, 32.4, 8.5]

# Exemplul 2:
# Funcții de primă clasă ca obiect explicit al Proc -
ex = Proc . nou { pune „Bună, lume!” }
ex . sunați # Bună ziua, lume!

# Exemplul 3:
# Funcție care returnează obiectul funcției lambda cu parametri
def is_multiple_of ( n )
    lambda { | x | x % n == 0 }
Sfârșit
multiple_four = is_multiple_of ( 4 )
multiple_patru . apel ( 16 )
#Adevărat
multiple_patru [ 15 ]
#fals

JavaScript

Funcțiile anonime, în JavaScript, sunt definite ca funcții non-anonime. De exemplu, funcția

 funcție add ( a , b ) { return a + b ; }

scrii anonim

 function ( a , b ) { return a + b ; }

și poate fi atribuit unei variabile

 var a = funcție ( a , b ) { return a + b ; }

sau trecut ca parametru unei alte funcții.

Din versiunea ES6 puteți utiliza o sintaxă alternativă mai slabă:

 ( a , b ) => { return a + b ; }

sau, chiar mai succint

 ( a , b ) => a + b

JavaScript acceptă funcții anonime autoinvocabile , adică sunt invocate chiar în momentul declarației. Acest mod este exploatat pe scară largă în bibliotecile de execuție, cum ar fi JQuery .

 // Definiție și executare imediată
( funcția ( a , b ) {
    alertă ( a + b );
}) ( 10 , 11 );

Sau, începând cu ES6 :

 alert ( (( a , b ) => a + b ) ( 10 , 11 ) );

TypeScript

 var add = ( x , y ) => { return x + y };
alertă ( adăugați ( 1 , 2 ));

Specificarea tipurilor (care sunt opționale în TypeScript):

 var add = ( x : number , y : number ) : number => { return x + y };
alertă ( adăugați ( 1 , 2 ));

C #

 int add = ( x , y ) => { return x + y };
Consolă . WriteLine ( „{0}” , adăugați ( 1 , 2 ));

Specificarea tipurilor (care în C #, în unele cazuri, sunt opționale):

 int add = ( int x , int y ) => { return x + y };
Consolă . WriteLine ( „{0}” , adăugați ( 1 , 2 ))

C ++

C ++ adaugă suport pentru funcții anonime începând cu versiunea 11 a standardului. [1]

 // Exemplul 1 - Funcție care adaugă două numere întregi

auto add = [] ( int x , int y ) -> int { return x + y }; // [capture_list] (parametri) -> return_type {function_body}
std :: cout << add ( 1 , 2 ); // Pentru a utiliza std :: cout trebuie să includeți <iostream>

In exemplul anterior, add variabila este de tip std::function<int(int, int)> , adică: std::function< tipo_restutuito ( tipi_dei_parametri )> [2] . Cu toate acestea, începând cu C ++ 11 este posibil să se omită tipul formal (cu precizie std::function<int(int, int)> ) folosind cuvântul cheie auto dacă tipul este deductibil în timpul compilării (ca în acest caz). [3]

Captarea variabilelor

În alte limbi (cum ar fi JavaScript, de exemplu) funcțiile lambda pot capta toate variabilele din sfera lor de aplicare, mai simplu, se poate spune că o lambda are acces la toate variabilele declarate înainte de lambda în sine. În C ++ puteți specifica la ce variabile are acces funcția lambda. De asemenea, puteți specifica dacă variabilele sunt accesibile prin valoare sau prin referință ( după valoare sau prin referință ); variabilele trecute prin valoare pot fi utilizate în modul numai citire. [2]

 / * Exemplul 2 - Funcție care captează variabile după valoare și
* încearcă să le modifice producând o eroare de compilare
* /

#include <iostream>

int main ( int argc , char ** argv ) {

    // „a” și „b” sunt inițializate la 0
    int a = 0 ;
    int b = 0 ;

    // „a” și „b” sunt tipărite
    std :: cout << "Înainte de editare \ n " ; 
    std :: cout << "a =" << a << std :: endl ;
    std :: cout << "b =" << b << std :: endl ;

    // Se creează o lambda care le surprinde pe toate
    // variabilele BY VALUE și încercați să le modificați
    // [=] captează toate variabilele după valoare (numai citire)
    auto f = [ = ] () -> nul {
        a = 1 ; // eroare: atribuirea variabilei de numai citire „a”
        b = 2 ; // eroare: atribuirea variabilei numai în citire „b”
    }

    // se numește „f”
    f ();

    // „a” și „b” sunt tipărite după modificare
    std :: cout << "După modificare \ n " ;
    std :: cout << "a =" << a << std :: endl ;
    std :: cout << "b =" << b << std :: endl ;
    
    retur 0 ;
}

Ieșirea compilatorului este după cum urmează:

 ~ $ g ++ -std = c ++ 11 exemplu2.cpp -o exemplu2
example2.cpp: În funcția lambda:
example2.cpp: 22: 11: eroare: atribuirea variabilei de numai citire „a”
        a = 1;
          ^
example2.cpp: 23: 11: eroare: atribuirea variabilei de numai citire „b”
        b = 2;
          ^

Pentru a corecta eroarea:

 // Exemplul 3 - Funcție care ia două variabile prin referință și le modifică

#include <iostream>

int main ( int argc , char ** argv ) {

    // „a” și „b” sunt inițializate la 0
    int a = 0 ;
    int b = 0 ;

    // „a” și „b” sunt tipărite
    std :: cout << "Înainte de editare \ n " ; 
    std :: cout << "a =" << a << std :: endl ;
    std :: cout << "b =" << b << std :: endl ;

    // Se creează o lambda care le surprinde pe toate
    // variabilele DE REFERINȚĂ și le modifică
    // [&] captează toate variabilele prin referință
    auto f = [ & ] () -> nul { 
        a = 1 ;
        b = 2 ;
    }

    // se numește „f”
    f ();

    // „a” și „b” sunt tipărite după modificare
    std :: cout << "După modificare \ n " ;
    std :: cout << "a =" << a << std :: endl ;
    std :: cout << "b =" << b << std :: endl ;
    
    retur 0 ;
}

Ieșirea programului este următoarea: Prima della modifica a=0 b=0 Dopo la modifica a=1 b=2 Puteți captura variabilele în următoarele moduri:

 // Captează toate după valoare (numai citire)
[ = ] ( parametri ...) -> return_type { / * ... * / } 

// Captează totul prin referință
[ & ] ( parametri ...) -> return_type { / * ... * / } 

// Captează „x”, „y”, „z” prin referință și nimic altceva
[ & x , & y , & z ] ( parametri ...) -> return_type { / * ... * / } 
// Captează „x”, „y”, „z” prin referință și orice altceva după valoare
[ = , & x , & y , & z ] ( parametri ...) -> return_type { / * ... * / } 

// Captează „a”, „b”, „c” după valoare și nimic altceva
[ a , b , c ] ( parametri ...) -> return_type { / * ... * / }  
// Captează „a”, „b”, „c” după valoare și orice altceva prin referință
[ & , a , b , c ] ( parametri ...) -> return_type { / * ... * / }

Funcții anonime de autoinvocare

C ++ (ca și alte limbi, de exemplu JavaScript) vă permite să declarați funcții anonime autoinvocabile , adică sunt invocate în momentul declarației:

 // Exemplul 4 - Funcție anonimă de auto-invocare care adaugă două numere întregi

([] ( int a , int b ) -> nul {
        std :: cout << a + b ; // Imprimați suma dintre „a” și „b”
}) ( 1 , 2 ); // Funcția este invocată trecând ca parametrii 1 și 2; va imprima 3

Java

În Java, funcțiile anonime au fost incluse în versiunea 8 (lansată în 2014) și pot fi specificate în conformitate cu următoarea sintaxă: [4]

 (Parametru1, parametru2) -> { bloc de cod }

De exemplu, următorul cod:

 Listă < T > newList = myList
		. stream ()
		. filtru ( t -> verificarea stării ( t ))
		. colecta ( Collectors . toList ());

este echivalentul funcțional al:

 Listă < T > newList = new ArrayList <> ();
pentru ( T t : lista mea ) {
	if ( verificaCondiție ( t )) {
		listă nouă . adăugați ( t );
	}
}

Notă

  1. ^ Funcții Lambda (de la C ++ 11) , pe it.cppreference.com .
  2. ^ a b ( IT ) Bjarne Stroustrup, limbaj C ++, bibliotecă standard, principii de programare (limbaj de programare C ++) , capitolul 11.4, Pearson Italia, 2015, ISBN 9788865184486 .
  3. ^ ( IT ) Bjarne Stroustrup, capitolul 6 , în limbaj C ++, bibliotecă standard, principii de programare (limbaj de programare C ++) , ediția a patra, Pearson Italia, 2015, ISBN 9788865184486 .
  4. ^ (EN) Java Lambda Expressions , pe w3schools.com, W3Schools . Adus de 30 aprilie 2021.

Elemente conexe

Informatică Portal IT : accesați intrările Wikipedia care se ocupă cu IT