Newsgroup: it.comp.www.php
Titolo: Generators

Li avete mai usati in produzione? Mi piacerebbe vedere qualche esempio
di codice reale dove il risparmio di RAM a discapito delle performace
sia risultato realmente utile.
 
-- 
g4b0, linux user n. 369000
http://brosulo.net
 

 
 
Ah, i generators, un'altra cosa di cui probabilmente nessuno sentiva il
bisogno ;) Ti posso fare qualche esempio che mi posso inventare su due piedi,
ma immagino questo lo possa fare anche te :D
 
Classicamente la cosa carina dei generators è che ci puoi costruire sopra il
meccanisimo di coroutines ma, visto che tanto PHP ha anche i thread a
disposizione, i casi in cui potrebbero essere utili è ridicolmente basso - 
magari come esercizio di stile o per fare il figo può andare ;)
 
Io non li ho mai usati (in PHP) perché boh, trovo più chiaro avere un ciclo
in vista e un livello d'intentazione in più piuttosto che una funzione
mascherata da array.
 
Ciao!


Be, puoi generare la serie di fibonacci senza instanziare Gb di ram, ma
non ho mai dovuto generare serie matematiche in nessun sito che ho
sviluppato :)
 
Onestamente faccio fatica a trovare un utilizzo *reale* per i
generators, infatti ho scritto qua per avere qualche spunto oppure conferme.
 
Per ora
 
conferme: 1
spunti: 0



No beh, li devi prendere come syntactic sugar, non come qualcosa di necessario.
 
Possono anche essere utili per fare refactoring, per esempio: qualasiasi
foreach() su un array grosso può essere riscritto facilmente con un generator
senza cambiare quasi nulla.
 
Oltretutto, probabilmente per chi viene da linguaggi funzionali il codice
scritto utilizzandoli può risultare più chiaro.
 
Ciao!

 senza cambiare quasi nulla.
 
In effetti il refactoring potrebbe essere un buon punto di aggancio per
i generators, dato che mantengono la logica degli array.
 
In sostanza scrivo codice senza badare al consumo di RAM, se poi vedo
che scoppia tutto so che posso ricorrere ai generators. È un ottimo modo
per evitare la premature optimization.


 sia risultato realmente utile.
 
No, e onestamente anche io fatico a vederne l'utilità, a parte i soliti 
generatori infiniti di numeri casuali o di sequenze numeriche.
 
Ma ho usato abbastanza gli iteratori, che sono un po' più complessi da 
creare (nemmeno tanto, visto la complicazione di capire yield...) ma 
anche molto più potenti, secondo me.
 
Sempre nella stessa applicazione di cui parlavo nell'altra mail, per il 
sistema di spooling delle mail, avevo necessità di caricare dati da un DB 
esterno, da file CSV e da altre fonti, mettendo tutto dentro la stessa 
tabella di DB finale (lo spooler, appunto)
 
Ho creato due generatori (uno è un light wrapper attorno a SplFileObject, 
l'altro attorno a un cursore di DB), e alla fine l'insert è qualcosa tipo
 
foreach($sources as $source) {
  foreach($source as $row) {
    $this->insert($row);
  }
}
 
Questo mi permette sia di astrarre la sorgente (CSV o DB resultset), sia 
di occupare un minimo di RAM (leggo una riga alla volta dal file o dal DB 
originale). Caricare in memoria 3-4 milioni di righe di CSV o di dati dal 
DB era impossibile, e usare nel ciclo un enorme switch che usasse fgetcsv 
da una parte e $stmt->fetchRow dall'altra diventava presto ingestibile.
 
La stessa cosa probabilmente la puoi fare coi generatori, sicuramente, 
ma... mi sta antipatico yield :D
 
Bye.

 anche molto più potenti, secondo me.
 
Mah, a detta di Josh Lockart i Generators ti permettono di avere gli
stessi risultati degli Iterators "without implement the Iterator
interface in a heavyweight class".
 
In effetti è comodo, nel caso in cui tornasse utile, poter implemetare
una funzione private all'interno della classe che fa il lavoro sporco,
senza dover istanziare oggetti ed amentià varie.


 senza dover istanziare oggetti ed amentià varie.
 
Se parliamo di prestazioni posso essere d'accordo, ma devo verificare. :)
Idealmente un generatore dovrebbe chiamare una sola funzione per ciclo, 
mentre un iteratore ne chiama almeno 3 (next(), valid() e current(), più 
key()). Ma credo che dietro le quinte anche per i generatori vengano 
chiamate le stesse funzioni, perché è foreach() che lo fa, non la 
struttura dati.
 
Se parliamo della differente comodità tra
 
$iter = new MyIterator($data);
foreach ($iter as $elem) { ... }
 
contro
 
foreach ($this->myiter($data) as $elem) { ... }
 
Allora basta implementare __staticCall nella classe:
 
class MyIterator {
 static public function __staticCall($data) { return new self($data); }
}
 
e lo usi con
 
foreach (MyIterator($data) as $elem) { ... }
 
Bye.