Lambda -lausekkeet C ++: ssa

Lambda Expressions C



Miksi Lambda Expression?

Harkitse seuraavaa väitettä:

intmyInt= 52;

Tässä myInt on tunniste, arvo. 52 on kirjain, prvalue. Nykyään on mahdollista koodata funktio erityisesti ja asettaa se kohtaan 52. Tällaista funktiota kutsutaan lambda -lausekkeeksi. Harkitse myös seuraavaa lyhyttä ohjelmaa:







#sisältää

käyttämällä nimiavaruustuntia;

intfn(intkautta)

{

intvastaus=kautta+ 3;

palatavastaus;

}


inttärkein()

{

fn(5);



palata 0;

}

Nykyään on mahdollista koodata funktio erityisesti ja asettaa se funktion kutsun, fn (5) argumentin 5 asemaan. Tällaista funktiota kutsutaan lambda -lausekkeeksi. Tässä asemassa oleva lambda -lauseke (funktio) on arvo.



Mikä tahansa literaali lukuun ottamatta merkkijonoa on prvalue. Lambda -lauseke on erikoisfunktio, joka sopisi kirjaimellisesti koodiin. Se on anonyymi (nimetön) toiminto. Tässä artikkelissa selitetään uusi ensisijainen lauseke C ++, jota kutsutaan lambda -lausekkeeksi. Perustiedot C ++: sta ovat edellytys tämän artikkelin ymmärtämiselle.



Artikkelin sisältö

Kuva lambda -ilmaisusta

Seuraavassa ohjelmassa funktio, joka on lambda -lauseke, määritetään muuttujalle:





#sisältää

käyttämällä nimiavaruustuntia;

autofn= [](intlopettaa)

{

intvastaus=lopettaa+ 3;

palatavastaus;

};


inttärkein()

{

automuuttuja=fn(2);

kustannus <<muuttuja<< '' n'';


palata 0;

}

Lähtö on:

5

Main () -funktion ulkopuolella on muuttuja fn. Sen tyyppi on auto. Automaattinen tässä tilanteessa tarkoittaa, että todellinen tyyppi, kuten int tai float, määräytyy toimeenpano -operaattorin oikean operandin (=) perusteella. Tehtäväoperaattorin oikealla puolella on lambda -lauseke. Lambda -lauseke on funktio ilman edeltävää palautustyyppiä. Huomaa hakasulkeiden [] käyttö ja sijainti. Funktio palauttaa 5, int, joka määrittää fn: n tyypin.



Main () -funktiossa on lause:

automuuttuja=fn(2);

Tämä tarkoittaa, että fn ulkopuolella main () päätyy funktion tunnisteeksi. Sen implisiittiset parametrit ovat lambda -lausekkeen parametrit. Muuttujan tyyppi on auto.

Huomaa, että lambda -lauseke päättyy puolipisteeseen, aivan kuten luokan tai rakenteen määritelmä, päättyy puolipisteeseen.

Seuraavassa ohjelmassa funktio, joka on lambda -lauseke, joka palauttaa arvon 5, on argumentti toiselle funktiolle:

#sisältää

käyttämällä nimiavaruustuntia;

mitätönmuufn(intnro 1,int (*ptr)(int))

{

intnro 2= (*ptr)(2);

kustannus <<nro 1<< '' <<nro 2<< '' n'';

}


inttärkein()

{

muufn(4,[](intlopettaa)

{

intvastaus=lopettaa+ 3;

palatavastaus;

});


palata 0;
}

Lähtö on:

Neljä viisi

Tässä on kaksi funktiota, lambda -lauseke ja otherfn () -funktio. Lambda -lauseke on otherfn (): n toinen argumentti, jota kutsutaan main (): ksi. Huomaa, että lambda-funktio (lauseke) ei pääty puolipisteeseen tässä puhelussa, koska se on tässä argumentti (ei erillinen funktio).

Funktion otherfn () määritelmän lambda -funktion parametri on funktion osoitin. Osoittimella on nimi, ptr. Nimeä ptr käytetään otherfn () -määrittelyssä lambda -funktion kutsumiseen.

Lausunto,

intnro 2= (*ptr)(2);

Määritelmässä otherfn () se kutsuu lambda -funktiota argumentilla 2. Puhelun paluuarvo, '(*ptr) (2)' lambda -funktiosta, on osoitettu no2: lle.

Yllä oleva ohjelma näyttää myös, miten lambda -toimintoa voidaan käyttää C ++ -soittotoimintokaaviossa.

Lambda Expressionin osat

Tyypillisen lambda -toiminnon osat ovat seuraavat:

[] () {}
  • [] on sieppauslauseke. Siinä voi olla esineitä.
  • () on parametriluettelo.
  • {} on funktion runko. Jos toiminto on yksin, sen tulee päättyä puolipisteeseen.

Sieppaa

Lambda -funktion määritelmä voidaan liittää muuttujaan tai käyttää argumenttina eri funktiokutsulle. Tällaisen funktiokutsun määritelmässä tulisi olla parametrina parametri, joka osoittaa funktion, joka vastaa lambda -funktion määritelmää.

Lambda -funktion määritelmä eroaa normaalifunktion määritelmästä. Se voidaan määrittää muuttujalle globaalissa laajuudessa; tämä muuttujalle määritetty toiminto voidaan myös koodata toisen funktion sisään. Kun sen runko on määritetty globaalille laajuusmuuttujalle, se voi nähdä muita globaalin laajuuden muuttujia. Kun sen runko on määritetty muuttujalle normaalin funktion määritelmän sisällä, se voi nähdä muut funktion laajuuden muuttujat vain sieppauslausekkeen avulla, [].

Sieppauslauseke [], joka tunnetaan myös nimellä lambda-johdantaja, sallii muuttujien lähettämisen ympäröivästä (toiminto) laajuudesta lambda-lausekkeen funktion runkoon. Lambda -lausekkeen funktiokappaleen sanotaan sieppaavan muuttujan, kun se vastaanottaa objektin. Ilman sieppauslauseketta [] muuttujaa ei voida lähettää ympäröivästä laajuudesta lambda -lausekkeen funktion runkoon. Seuraava ohjelma havainnollistaa tätä päätoimintoalueella () ympäröivänä laajuutena:

#sisältää

käyttämällä nimiavaruustuntia;

inttärkein()

{

intid= 5;


autofn= [id]()

{

kustannus <<id<< '' n'';

};

fn();


palata 0;

}

Lähtö on 5 . Ilman nimeä, id, [], lambda -lauseke ei olisi nähnyt main () -funktion laajuuden muuttujaa id.

Sieppaus viitteellä

Edellä oleva esimerkki kaappauslausekkeen käytöstä on kaappaaminen arvon perusteella (katso yksityiskohdat alla). Viitattaessa kaappaukseen muuttujan sijainti (tallennus), esim. Id edellä, ympäröivästä laajuudesta, on saatavilla lambda -funktion rungon sisällä. Joten muuttujan arvon muuttaminen lambda -funktion rungon sisällä muuttaa saman muuttujan arvoa ympäröivässä laajuudessa. Jokaista sieppauslausekkeessa toistettua muuttujaa edeltää ampersand (&) tämän saavuttamiseksi. Seuraava ohjelma havainnollistaa tätä:

#sisältää

käyttämällä nimiavaruustuntia;

inttärkein()

{

intid= 5; kelluaft= 2.3; hiiltyäch= 'TO';

autofn= [&tunnus,&ft,&ch]()

{

id= 6;ft= 3.4;ch= 'B';

};

fn();

kustannus <<id<< ',' <<ft<< ',' <<ch<< '' n'';

palata 0;

}

Lähtö on:

6, 3.4, B

Vahvistetaan, että muuttujien nimet lambda -lausekkeen funktion rungossa ovat samoille muuttujille lambda -lausekkeen ulkopuolella.

Tallennus arvon mukaan

Arvoa kaapattaessa kopio muuttujan sijainnista ja ympäröivästä laajuudesta on saatavilla lambda -funktion rungon sisällä. Vaikka lambda -funktion rungon sisällä oleva muuttuja on kopio, sen arvoa ei voi muuttaa rungon sisällä toistaiseksi. Arvon kaappaamisen saavuttamiseksi mitään sieppauslausekkeessa toistettua muuttujaa ei edellytä mikään. Seuraava ohjelma havainnollistaa tätä:

#sisältää

käyttämällä nimiavaruustuntia;

inttärkein()

{

intid= 5; kelluaft= 2.3; hiiltyäch= 'TO';

autofn= [id, ft, ch]()

{

// id = 6; ft = 3,4; ch = 'B';

kustannus <<id<< ',' <<ft<< ',' <<ch<< '' n'';

};

fn();

id= 6;ft= 3.4;ch= 'B';

kustannus <<id<< ',' <<ft<< ',' <<ch<< '' n'';

palata 0;

}

Lähtö on:

5, 2.3, A.

6, 3.4, B

Jos kommentin ilmaisin poistetaan, ohjelma ei käännä. Kääntäjä antaa virheilmoituksen, että funktion rungon lambda -lausekkeen määritelmän sisällä olevia muuttujia ei voi muuttaa. Vaikka muuttujia ei voida muuttaa lambda -funktion sisällä, niitä voidaan muuttaa lambda -funktion ulkopuolella, kuten yllä olevan ohjelman tulos osoittaa.

Sieppausten sekoittaminen

Kaappaamista viitteellä ja kaappaamista arvon avulla voidaan sekoittaa, kuten seuraava ohjelma osoittaa:

#sisältää

käyttämällä nimiavaruustuntia;

inttärkein()

{

intid= 5; kelluaft= 2.3; hiiltyäch= 'TO'; boolbl= totta;


autofn= [id, ft,&ch,&bl]()

{

ch= 'B';bl= väärä;

kustannus <<id<< ',' <<ft<< ',' <<ch<< ',' <<bl<< '' n'';

};

fn();


palata 0;

}

Lähtö on:

5, 2.3, B, 0

Kun kaikki on otettu, viitataan:

Jos kaikki kaapattavat muuttujat tallennetaan viittauksella, vain yksi & riittää sieppauslausekkeeseen. Seuraava ohjelma havainnollistaa tätä:

#sisältää

käyttämällä nimiavaruustuntia;

inttärkein()

{

intid= 5; kelluaft= 2.3; hiiltyäch= 'TO'; boolbl= totta;


autofn= [&]()

{

id= 6;ft= 3.4;ch= 'B';bl= väärä;

};

fn();

kustannus <<id<< ',' <<ft<< ',' <<ch<< ',' <<bl<< '' n'';


palata 0;

}

Lähtö on:

6, 3.4, B, 0

Jos jotkin muuttujat tallennetaan viitteellä ja toiset arvolla, yksi & edustaa kaikkia viittauksia, ja loput eivät edellytä mitään, kuten seuraava ohjelma osoittaa:

käyttämällä nimiavaruustuntia;

inttärkein()

{

intid= 5; kelluaft= 2.3; hiiltyäch= 'TO'; boolbl= totta;


autofn= [&, tunnus, ft]()

{

ch= 'B';bl= väärä;

kustannus <<id<< ',' <<ft<< ',' <<ch<< ',' <<bl<< '' n'';

};

fn();


palata 0;

}

Lähtö on:

5, 2.3, B, 0

Huomaa, että & yksinään (eli, eikä tunnuksen perässä) on oltava kaappauslausekkeen ensimmäinen merkki.

Kun kaikki on otettu, ovat arvon mukaan:

Jos kaikki kaapattavat muuttujat tallennetaan arvon mukaan, vain yksi = riittää sieppauslausekkeeseen. Seuraava ohjelma havainnollistaa tätä:

#sisältää

käyttämällä nimiavaruustuntia;

inttärkein()
{

intid= 5; kelluaft= 2.3; hiiltyäch= 'TO'; boolbl= totta;


autofn= [=]()

{

kustannus <<id<< ',' <<ft<< ',' <<ch<< ',' <<bl<< '' n'';

};

fn();


palata 0;


}

Lähtö on:

5, 2.3, A, 1

Huomautus : = on vain luku, toistaiseksi.

Jos jotkin muuttujat halutaan tallentaa arvon perusteella ja toiset viittauksella, yksi = edustaa kaikkia vain luku -muotoisia muuttujia ja muilla on &, kuten seuraava ohjelma osoittaa:

#sisältää

käyttämällä nimiavaruustuntia;

inttärkein()

{

intid= 5; kelluaft= 2.3; hiiltyäch= 'TO'; boolbl= totta;


autofn= [=,&ch,&bl]()

{

ch= 'B';bl= väärä;

kustannus <<id<< ',' <<ft<< ',' <<ch<< ',' <<bl<< '' n'';

};

fn();


palata 0;

}

Lähtö on:

5, 2.3, B, 0

Huomaa, että = yksin on oltava kaappauslausekkeen ensimmäinen merkki.

Klassinen takaisinsoitotoiminto Lambda -lausekkeella

Seuraava ohjelma näyttää, miten klassinen takaisinsoittotoiminto voidaan tehdä lambda -lausekkeella:

#sisältää

käyttämällä nimiavaruustuntia;

hiiltyä *lähtö;


autocba= [](hiiltyäulos[])

{

lähtö=ulos;

};



mitätönmainFunc(hiiltyätulo[],mitätön (*varten)(hiiltyä[]))

{

(*varten)(tulo);

kustannus<<'' päätoiminnolle ''<<'' n'';

}


mitätönfn()

{

kustannus<<'Nyt'<<'' n'';

}


inttärkein()

{

hiiltyätulo[] = 'soittotoimintoa varten';

mainFunc(tulo, cba);

fn();

kustannus<<lähtö<<'' n'';



palata 0;

}

Lähtö on:

päätoimintoa varten

Nyt

soittotoimintoa varten

Muista, että kun lambda -lausekkeen määritelmä on määritetty muuttujalle globaalissa laajuudessa, sen funktion runko voi nähdä globaalimuuttujat käyttämättä sieppauslauseketta.

Perä-paluu-tyyppi

Lambda -lausekkeen palautustyyppi on automaattinen, mikä tarkoittaa, että kääntäjä määrittää palautustyypin palautuslausekkeesta (jos sellainen on). Jos ohjelmoija todella haluaa ilmoittaa palautustyypin, hän tekee sen kuten seuraavassa ohjelmassa:

#sisältää

käyttämällä nimiavaruustuntia;

autofn= [](intlopettaa) -> int

{

intvastaus=lopettaa+ 3;

palatavastaus;

};


inttärkein()

{

automuuttuja=fn(2);

kustannus <<muuttuja<< '' n'';


palata 0;

}

Tulos on 5. Parametriluettelon jälkeen nuolioperaattori kirjoitetaan. Tätä seuraa palautustyyppi (int tässä tapauksessa).

Päättäminen

Harkitse seuraavaa koodisegmenttiä:

rakenneCla

{

intid= 5;

hiiltyäch= '';

}obj1, obj2;

Tässä Cla on rakenneluokan nimi. Obj1 ja obj2 ovat kaksi objektia, jotka luodaan strukturiluokasta. Lambda -ilmaisu on samanlainen toteutuksessa. Lambda -funktion määritelmä on eräänlainen luokka. Kun lambda -funktiota kutsutaan (kutsutaan), objekti luodaan sen määritelmästä. Tätä objektia kutsutaan sulkemiseksi. Sulkeminen tekee sen työn, jonka lambdan odotetaan tekevän.

Lambda -lausekkeen koodaus kuten yllä oleva rakenne, obj1 ja obj2 korvataan kuitenkin vastaavien parametrien argumenteilla. Seuraava ohjelma havainnollistaa tätä:

#sisältää

käyttämällä nimiavaruustuntia;

autofn= [](intparam1,intparam2)

{

intvastaus=param1+param2;

palatavastaus;

} (2,3);


inttärkein()

{

automissä=fn;

kustannus <<missä<< '' n'';


palata 0;

}

Tulos on 5. Argumentit ovat suluissa 2 ja 3. Huomaa, että lambda -lausekkeen funktiokutsu fn ei ota argumentteja, koska argumentit on jo koodattu lambda -funktion määritelmän lopussa.

Johtopäätös

Lambda -lauseke on anonyymi funktio. Se koostuu kahdesta osasta: luokka ja objekti. Sen määritelmä on eräänlainen luokka. Kun lauseketta kutsutaan, määritelmästä muodostuu objekti. Tätä objektia kutsutaan sulkemiseksi. Sulkeminen tekee sen työn, jonka lambdan odotetaan tekevän.

Jotta lambda-lauseke saisi muuttujan ulkoisesta funktioalueesta, se tarvitsee ei-tyhjän sieppauslausekkeen funktion runkoon.