Ciò che viene discusso è essenzialmente la differenza tra una metodologia di elaborazione basata su push e una basata su pull. In un sistema push come questa libreria di pipe, si stabilisce una catena di elaborazione e ogni fase di elaborazione trasferisce i suoi dati direttamente al successivo. In un sistema pull come gli intervalli, si stabilisce una rappresentazione dei dati, a cui è possibile accedere e modificare in base alle esigenze. L'elaborazione non avviene da sola; succede solo quando qualcuno tenta di consumare l'intervallo.
Le operazioni unzip
e fork
sono entrambe operazioni da una a molte: prendono un singolo input e lo mappano a molte operazioni di elaborazione.
Come sistema push, la libreria di pipe può gestire operazioni da una a molte grazie alla struttura della sua API. Un'operazione è rappresentata da una chiamata di funzione; l'input è implicito dal punto di utilizzo (utilizzandolo >>=
o passandolo a un processore). I parametri della funzione definiscono il suo output (ignorando i parametri pensati per il processore stesso). E poiché le funzioni C ++ possono avere un numero arbitrario di parametri, naturalmente fallisce un'operazione di mappatura da uno a molti. È sufficiente fornire processori appropriati per i vari output.
Come sistema pull, gli intervalli si basano su valori di ritorno. C ++ non ha un meccanismo linguistico per restituire più valori, quindi il meglio che possiamo fare è restituire un "valore" che rappresenti più valori.
Tuttavia, il concatenamento dell'adattatore di portata si basa in definitiva sugli input che sono intervalli . E un "'valore' che rappresenta più valori" non è esso stesso un intervallo. Può contenere intervalli, ma ciò non lo rende un intervallo.
Quindi ora devi prendere questo tipo decisamente "non di portata" e far funzionare tutti i tuoi adattatori di portata. L'applicazione di un adattatore di intervallo deve trasmettere tale operazione attraverso il tipo, creando un'operazione molti-a-molti. Fare questo non è facile.
Ma soprattutto ... probabilmente non è quello che vuoi . Se sei fork
un intervallo, allora quasi sicuramente vuoi fare un'elaborazione diversa sugli intervalli replicati. E questo spegne completamente ogni possibilità di usare l' |
operazione per farlo. Dovrai creare modi per applicare gli adattatori a parti specifiche di queste tuple. E quei modi appariranno sempre più come un processore basato su push.
Alla fine della giornata, un sistema di tipo pull ha una sola uscita per ogni livello. È solo una parte del concetto chiave di tale API: ogni fase di elaborazione genera un intervallo. Questo ha i suoi vantaggi (elaborazione lenta) ma rappresentare una o più operazioni è una delle sue aree deboli.
Gli intervalli possono certamente avere una unzip
funzione (in fork
realtà sta solo copiando l'intervallo). Ma non sarebbe un |
adattatore di stile; sarebbe una funzione che prende un intervallo su un tipo scomponibile e restituisce una tupla di intervalli. Se vuoi fare più elaborazioni con loro, allora dovresti memorizzare la tupla in un valore, accedere ai singoli elementi e usarli come ritieni opportuno.