I like to define sequences recursively as follows:
let rec startFrom x =
seq {
yield x;
yield! startFrom (x + 1)
}
I’m not sure if recursive sequences like this should be used in practice. The yield! appears to be tail recursive, but I’m not 100% sure since its being called from inside another IEnumerable. From my point of view, the code creates an instance of IEnumerable on each call without closing it, which would actually make this function leak memory as well.
Will this function leak memory? For that matter is it even “tail recursive”?
[Edit to add]: I’m fumbling around with NProf for an answer, but I think it would be helpful to get a technical explanation regarding the implementation of recursive sequences on SO.
I’m at work now so I’m looking at slightly newer bits than Beta1, but on my box in Release mode and then looking at the compiled code with .Net Reflector, it appears that these two
generate almost identical MSIL code when compiled in ‘Release’ mode. And they run at about the same speed as this C# code:
(e.g. I ran all three versions on my box and printed the millionth result, and each version took about 1.3s, +/- 1s). (I did not do any memory profiling; it’s possible I’m missing something important.)
In short, I would not sweat too much thinking about issues like this unless you measure and see a problem.
EDIT
I realize I didn’t really answer the question… I think the short answer is “no, it does not leak”. (There is a special sense in which all ‘infinite’ IEnumerables (with a cached backing store) ‘leak’ (depending on how you define ‘leak’), see
Avoiding stack overflow (with F# infinite sequences of sequences)
for an interesting discussion of IEnumerable (aka ‘seq’) versus LazyList and how the consumer can eagerly consume LazyLists to ‘forget’ old results to prevent a certain kind of ‘leak’.)