2012-02-08 21 views
16

No puedo entender las diferencias entre la secuencia y LazyList. Ambos son flojos y potencialmente infinitos. Mientras seq<'T> es IEnumerable<'T> de .NET framework, LazyList se incluye en F# PowerPack. En la práctica, encuentro secuencias mucho más a menudo que LazyList s.Secuencia frente a LazyList

¿Cuáles son sus diferencias en términos de rendimiento, uso, legibilidad, etc.? ¿Cuáles son las razones de tan mala reputación de LazyList en comparación con la de seq?

Respuesta

31

LazyList calcula cada elemento una sola vez independientemente de cuántas veces se recorre la lista. De esta forma, está más cerca de una secuencia devuelta desde Seq.cache (en lugar de una secuencia típica). Pero, aparte del almacenamiento en caché, LazyList se comporta exactamente como una lista: utiliza una estructura de lista debajo del capó y admite la coincidencia de patrones. Por lo tanto, podría decir: use LazyList en lugar de seq cuando necesite lista semántica y almacenamiento en caché (además de la pereza).

En cuanto ambos son infinitos, el uso de memoria de seq es constante, mientras que LazyList es lineal.

Puede valer la pena leer estos docs.

+0

+1, genial, no sabía acerca de la parte de almacenamiento en caché. ¿Podría darnos un ejemplo que requiere tanto pereza como semántica de la lista? – pad

+0

Atravesar una secuencia mientras se accede simultáneamente a múltiples elementos se puede hacer con un 'seq', pero es mucho más limpio usando' LazyList' + matching de patrón. – Daniel

+0

Ver p. http://stackoverflow.com/questions/3484315/how-to-merge-sorted-sequences-in-f y http://stackoverflow.com/questions/1306140/f-why-is-using-a-sequence- mucho-lento-que-usa-una-lista-en-este-ejemplo/1306267 # 1306267 – Brian

19

Además de la respuesta de Daniel, creo que la principal diferencia práctica es cómo procesa las estructuras LazyList o seq (o cálculos).

  • Si desea procesar LazyList, que normalmente sería escribir una función recursiva utilizando la coincidencia de patrones (bastante similar al procesamiento de las listas normales # F)

  • Si desea procesar seq, se puede utilizar funciones incorporadas o tiene que escribir el código imperativo que llama al GetEnumerator y luego usa el enumerador devuelto en un bucle (que puede escribirse como una función recursiva, pero mutará el enumerador). No puede usar el estilo usual de cabeza/cola (usando Seq.tail y Seq.head), porque eso es extremadamente ineficiente, porque seq no mantiene los elementos evaluados y el resultado de Seq.head necesita volver a iterarse desde el principio.

En cuanto a la reputación de seq y LazyList, creo que el diseño F # biblioteca adopta un enfoque pragmático - desde seq es en realidad .NET IEnumerable, es muy conveniente para la programación .NET (y también es bueno porque se puede tratar otras colecciones como seq). Las listas diferidas no son tan frecuentes y, por lo tanto, la lista F # normal y seq son suficientes en la mayoría de los escenarios.