A PHP yield kulcsszava hogy működik pontosan?
Mármint a mögöttes dolgokra vagyok kíváncs, a példákat értem. Hogy csinálja,hogy alig fogyaszt memóriát,ellenben egy tömbbel? Azt tudom,hogy egy Generator osztály van mögötte,de ez pontosan hogy működik a háttérben?
Például itt az explode eredményét tárolja valahol,nem? Hiába közvetlen a foreach-ben van. Vagy ahogy állítódik elő az explode() eredménye,már írja is ki?
Köszönöm a válaszokat előre is!
Nincsen jelentoseget a kerdes szempontjabol a php-nak. Mas nyelveknel is van yield es mindenhol ugyan az a szerepe.
Lehet, hogy most ezzel nagy hulyeseget fogok mondani, szoval javitsatok.ki, ha tevedek.
A yield egy olyan utasitas, ami a futo szalon megallitja az aktualis utasitas (pl. iteracio) futasat. A break-el ellentetben nem lep ki teljesen, hanem csak megallitja a futo kodot, amit aztan kesobb onnan folytatodik, ahol abbahagytuk. Ha egy 100 elemu listan iteralsz es az 59. iteracio vegen yield-elsz, akkor az iteracio az 59. iteraciotol fog folytatodni.
Egy (talan hasznos gyakorlati pelda) az lehet, hogy valami nagy szamitasigenyu muveletet vegzel egy nagy listan mondjuk. Az iteraciod sokaig tart, de tudod, hogy tobb olyan eredmenye is fog menet kozben szuletni, amivel aztan szeretnel kezdeni valamit. Ezért ha egy ilyen eredmenyed megvan, akkor yield-elsz az iteraciobol, majd jobb esetben egy masik szalon elkezdesz dolgozni a kapott eredmennyel. Miutan a masik szal megkapta a feladat, folytatodik az "eredeti" szalon a futas onnan, ahol abbahagytad.
A yield előnye elsősorban a memóriahasználatban van. Lehetővé teszi, hogy nagyon nagy (potenciálisan végtelen) adathalmazon tudj végigiterálni, minimális memóriahasználattal.
A linkelt példa kissé hibás, mert az illető csak az elején, és a végén mérte a memóriát, így amit nem mutat a példája, hogy a kód közepén ugyanúgy megugrott a memóriahasználat. Hovatovább, a memóriamegtakarítást az ő esetében nem a generátor használata, hanem az enkapszuláció eredményezte (a fájlt a függvényen belül olvasta be, és a függvényből kilépve így felszaabdult az arra allokált memóriaterület)
Ha van egy kész tömböd/collection-öd, miegyebed, akkor a generátor használata fölöslegessé válik. Viszont ha van mondjuk egy nagyon hosszú fájlod amit egyben nem tudnál beolvasni, mert több GB méretű, akkor egy generátorfüggvénnyel meg tudod csinálni, hogy soronként olvasod be a fájlt, és minden sor beolvasásakor visszaadod az aktuális sort feldolgozásra. Így a generátorfüggvényed kívülről pontosan úgy viselkedik mint egy iterálható állomány, viszont egyszerre mindig csak 1 sort tárolsz a memóriában. Ezt egyébként meg lehet oldani generátorfüggvény nélkül is, csak kell egy ciklus, ami addig fut amíg a file végére nem érsz, és ugyanúgy soronként olvasol be.
Egy még passzosabb példa az, amikor nem feldolgozol, hanem előállítasz adatot. Méghozzá potenciálisan végtelen mennyiségűt. Mondjuk egy random számgenerátor. Lényegében ugyanezen az elven működik. Van egy kezdeti seed, amiből kiindul, és egy algoritmus alapján minden lépésben ki tudja számolni a következő véletlenszámot. Nem számol előre, nem tárol le semmit. Csak kiszámítja a következő számot. Így a végtelenségig tud működni anélkül, hogy megugrana a memóriahasználat. Az egyetlen különbség, hogy a php-s rand()-ot nem tudod berakni egy foreach-be. De létrehozhatsz egy struktúrát ami megvalósítja az Iterator interfészt, és a megfelelő metódusaiban hívhatod a rand()-ot. Vagy simán berakhatod egy generátorfüggvénybe, és nincs semmi más dolgod.
A generátor igazából egy kényelmi funkció, funkcionálisan kiváltható egy Iterator interfészt megvalósító objektummal, csak annál sokkal kompaktabb, így sok esetben kényelmesebb ezt használni.
Kapcsolódó kérdések:
Minden jog fenntartva © 2024, www.gyakorikerdesek.hu
GYIK | Szabályzat | Jogi nyilatkozat | Adatvédelem | Cookie beállítások | WebMinute Kft. | Facebook | Kapcsolat: info(kukac)gyakorikerdesek.hu
Ha kifogással szeretne élni valamely tartalommal kapcsolatban, kérjük jelezze e-mailes elérhetőségünkön!