2012-02-08 13 views
16

Non riesco a comprendere le differenze tra la sequenza e LazyList. Sono entrambi pigri e potenzialmente infiniti. Mentre seq<'T> è IEnumerable<'T> da .NET framework, LazyList è incluso in F# PowerPack. In pratica, incontro sequenze molto più spesso di LazyList s.Sequence vs LazyList

Quali sono le loro differenze in termini di prestazioni, utilizzo, leggibilità, ecc.? Quali sono le ragioni di una così pessima reputazione di LazyList rispetto a quella di seq?

risposta

31

LazyList calcola ciascun elemento una sola volta indipendentemente dal numero di volte che l'elenco viene attraversato. In questo modo, è più vicino a una sequenza restituita da Seq.cache (anziché una sequenza tipica). Ma, oltre alla memorizzazione nella cache, LazyList si comporta esattamente come un elenco: utilizza una struttura di elenco sotto il cofano e supporta la corrispondenza del modello. Quindi potresti dire: usa LazyList invece di seq quando hai bisogno di elencare la semantica e il caching (oltre alla pigrizia).

Considerando che entrambi sono infiniti, l'utilizzo della memoria di seq è costante mentre lo LazyList è lineare.

Questi docs possono valere una lettura.

+0

+1, bello, non sapevo nulla della cache. Potresti dare un esempio che richiede sia la pigrizia che la semantica delle liste? – pad

+0

Attraversare una sequenza mentre si accede simultaneamente a più elementi può essere fatto con un 'seq', ma è molto più pulito usando la corrispondenza del modello' LazyList' +. – Daniel

+0

Vedere per es. http://stackoverflow.com/questions/3484315/how-to-merge-sorted-sequences-in-f e http://stackoverflow.com/questions/1306140/f-why-is-using-a-sequence- così-molto-più-lento-di-usare-un-elenco-in-questo-esempio/1306267 # 1306267 – Brian

19

Oltre alla risposta di Daniel, penso che la principale differenza pratica sia il modo in cui si elaborano le strutture LazyList o seq (o calcoli).

  • Se si desidera elaborare LazyList, è in genere scrivere una funzione ricorsiva utilizzando pattern matching (molto simile al trattamento dei normali # liste F)

  • Se si desidera elaborare seq, è possibile l'uso funzioni built-in o devi scrivere il codice imperativo che chiama GetEnumerator e quindi usa l'enumeratore restituito in un ciclo (che può essere scritto come funzione ricorsiva, ma muterà l'enumeratore). Non è possibile utilizzare il solito stile head/tail (utilizzando Seq.tail e Seq.head), perché questo è estremamente inefficiente, poiché seq non mantiene gli elementi valutati e il risultato di Seq.head deve essere ripetuto dall'inizio.

Per quanto riguarda la reputazione di seq e LazyList, penso che il design F # biblioteca ha un approccio pragmatico - dal momento che è in realtà seq NET IEnumerable, è molto conveniente per la programmazione .NET (ed è anche bello perché si può trattare altre raccolte come seq). Gli elenchi pigri non sono così frequenti e la lista F # così normale e lo seq sono sufficienti nella maggior parte degli scenari.

Problemi correlati