Последовательность против LazyList
Я не могу обернуть голову вокруг различий между последовательностью и LazyList
, Они оба ленивы и потенциально бесконечны. В то время как seq<'T>
является IEnumerable<'T>
из.NET Framework, LazyList
входит в F# PowerPack. На практике я встречаю последовательности намного чаще, чем LazyList
s.
Каковы их различия с точки зрения производительности, использования, читаемости и т. Д.? Каковы причины такой плохой репутации LazyList
по сравнению с seq
?
2 ответа
LazyList
вычисляет каждый элемент только один раз, независимо от того, сколько раз был пройден список. Таким образом, это ближе к последовательности, возвращаемой из Seq.cache
(а не типичная последовательность). Но, кроме кеширования, LazyList
ведет себя точно так же, как список: он использует структуру списка под капотом и поддерживает сопоставление с образцом. Так что вы можете сказать: использовать LazyList
вместо seq
когда вам нужна семантика списка и кэширование (в дополнение к лени).
Что касается того, что оба бесконечны, seq
использование памяти постоянное время LazyList
S является линейным.
Эти документы могут стоить прочитать.
В дополнение к ответу Даниэля, я думаю, что основное практическое отличие состоит в том, как вы обрабатываете LazyList
или же seq
структуры (или вычисления).
Если вы хотите обработать
LazyList
вы обычно пишете рекурсивную функцию, используя сопоставление с образцом (очень похоже на обработку обычных списков F#)Если вы хотите обработать
seq
, вы можете использовать встроенные функции или написать императивный код, который вызываетGetEnumerator
и затем использует возвращенный перечислитель в цикле (который может быть записан как рекурсивная функция, но он будет мутировать перечислитель). Вы не можете использовать обычный стиль головы / хвоста (используяSeq.tail
а такжеSeq.head
), потому что это крайне неэффективно - потому чтоseq
не сохраняет оцененные элементы и результатSeq.head
нужно повторить с самого начала.
Что касается репутации seq
а также LazyList
Я думаю, что дизайн библиотеки F# использует прагматичный подход - так как seq
на самом деле.NET IEnumerable
, это довольно удобно для программирования.NET (и это также хорошо, потому что вы можете рассматривать другие коллекции как seq
). Ленивые списки не так часты, и поэтому нормальный список F# и seq
достаточно в большинстве сценариев.