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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions