Skip to content

Inconsistent behavior of the Scan operator #1672

@veloek

Description

@veloek

The implementation of the Scan operator differs between Ix (both sync and async) and Rx with regards to the first element.

The source code contains a comment explaining the behavior for Ix stating it's compatible with Rx (but that's not actually the case):

// NB: Implementations of Scan never yield the first element, unlike the behavior of Aggregate on a sequence with one
//     element, which returns the first element (or the seed if given an empty sequence). This is compatible with Rx
//     but one could argue whether it was the right default.

This test code demonstrates the issue:

var ob = Enumerable.Range(0, 3).ToObservable();
var ae = Enumerable.Range(0, 3).ToAsyncEnumerable();

var obResult = await ob.Scan((acc, i) => i).ToList(); // 0, 1, 2
var aeResult = await ae.Scan((acc, i) => i).ToListAsync(); // 1, 2

var isSame = aeResult.SequenceEqual(obResult); // false

Furthermore, the implementation of Scan in MoreLINQ yield the first element, adding to the confusion when switching between libraries.

I understand that it's less than ideal to change the behavior of existing operators, but in this case I think it's worth considering due to the current inconsistency.

I would be happy to make a PR if you agree it should be changed.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions