Я сейчас на работе, поэтому я смотрю на немного более новые биты, чем Beta1, но на моем компьютере в режиме Release, а затем смотрю на скомпилированный код с .Net Reflector, кажется, что эти два
let rec startFromA x =
seq {
yield x
yield! startFromA (x + 1)
}
let startFromB x =
let z = ref x
seq {
while true do
yield !z
incr z
}
генерирует практически идентичный код MSIL при компиляции в режиме «Release». И они работают примерно с той же скоростью, что и этот код C #:
public class CSharpExample
{
public static IEnumerable<int> StartFrom(int x)
{
while (true)
{
yield return x;
x++;
}
}
}
(например, я запустил все три версии на своем боксе и напечатал миллионный результат, и каждая версия заняла около 1,3 с, +/- 1 с). (Я не делал никакого профилирования памяти; возможно, я упускаю что-то важное.)
Короче говоря, я бы не стал слишком много думать о таких вещах, если бы вы не измерили и не увидели проблему.
EDIT
Я понимаю, что на самом деле я не ответил на вопрос ... Я думаю, что короткий ответ "нет, он не протекает". (Существует особый смысл, в котором все «бесконечные» IEnumerables (с кэшированным резервным хранилищем) «утечка» (в зависимости от того, как вы определяете «утечка»), см.
Предотвращение переполнения стека (с F # бесконечными последовательностями последовательностей)
для интересного обсуждения IEnumerable (также известный как seq) против LazyList и того, как потребитель может охотно использовать LazyLists, чтобы «забыть» старые результаты, чтобы предотвратить определенный вид «утечки».)