Skip to content

Seq.init does not save values as suggested in description #14233

@abelbraaksma

Description

@abelbraaksma

The description and tooltip of Seq.init are as follows (emphasis mine):

Generates a new sequence which, when iterated, will return successive elements by calling the given function, up to the given count. Each element is saved after its initialization. The function is passed the index of the item being generated.

This suggests that for any sequence, the initializer is called only once and that successive access would use the saved value. I was inspecting the code and couldn't find how this was done and it turns out, it isn't. Not really, at least.

Repro steps

Basically, just this:

> let mutable i = 0;;
val mutable i: int = 0

> let s = Seq.init 10 (fun x -> i <- i + 1; i);;
val s: seq<int>

> Seq.last s;;
val it: int = 10

> Seq.last s;;
val it: int = 20

> i;;
val it: int = 20

Expected behavior

If the values from the generator were indeed saved, the initializer function would not be called again. However, the Seq.last returns different values, which means the mutable int I used gets updated again.

Actual behavior

The values aren't saved. At least not in the way I'd expect. They are saved momentarily for a call to Current, in such cases where you would use the IEnumerator<_>.Current directly. This saving itself is done in a Lazy<_> type to prevent problems if multiple threads read the value.

Known workarounds

Just ensure you don't write an expensive function as generator.

Related information

It's very well possible that this is "expected", and it is likely being used with side effects in practice. I'm bringing this up to discuss a better description for this function, as the way it is currently written, it confused me and possibly others.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Area-XmlDocsxmldoc generation, xmldoc contentBugImpact-Low(Internal MS Team use only) Describes an issue with limited impact on existing code.good first issuehelp wanted

    Type

    Projects

    Status

    New

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions