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
- Lambda Expressionin osat
- Sieppaa
- Klassinen takaisinsoitotoiminto Lambda -lausekkeella
- Perä-paluu-tyyppi
- Päättäminen
- Johtopäätös
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:
5Main () -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ä viisiTä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, BVahvistetaan, 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, 0Kun 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, 0Jos 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, 0Huomaa, 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, 1Huomautus : = 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, 0Huomaa, 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 vartenNyt
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.