-
Notifications
You must be signed in to change notification settings - Fork 3k
scan operator description might be confusing when not using any seed #4348
Description
Documentation Related To Component:
scan
Please check those that apply
- typo
- documentation doesn't exist
- documentation needs clarification
- error(s) in example
- needs example
Description Of The Issue
The last paragraph in scan's docblock says (emphasis is mine):
Returns an Observable that applies a specified
accumulatorfunction to each item emitted by the source Observable. If aseedvalue is specified, then that value will be used as the initial value for the accumulator. If no seed value is specified, the first item of the source is used as the seed.
However, the actual scan behavior isn't exactly like this:
...applies a specified accumulator function to each item emitted by the source Observable
It doesn't apply the accumulator function to every item if I don't set any seed. In that case it just passes the first emission through without calling accumulator:
from(['a', 'b', 'c']).pipe(
scan<string, number>((acc, value, index) => {
console.log(value, index);
return 0;
}),
).subscribe();
This will make the following output even when the first item was "a":
b 0
c 1
This is the relevant code:
rxjs/src/internal/operators/scan.ts
Lines 98 to 105 in de9d2e4
| protected _next(value: T): void { | |
| if (!this.hasSeed) { | |
| this.seed = value; | |
| this.destination.next(value); | |
| } else { | |
| return this._tryNext(value); | |
| } | |
| } |
Demo: https://stackblitz.com/edit/rxjs6-demo-ynfnan
So even though the sequence started with "a" the accumulator function was called for the first time for "b". Also the index passed started at 0 for the second item (does index count how many times the function was called or does it count the number of items that went through this operator?).
the first item of the source is used as the seed.
From the last sentence I would guess that the accumulator function will be called even for the first value like this order (even though it is a little weird):
accumulator('a', 'a', 0);
accumulator(..., 'b', 1);
accumulator(..., 'c', 2);
... while in fact it's called like this:
accumulator('a', 'b', 0);
accumulator(..., 'c', 1);
So maybe I'm just dumb but the description and actual behavior without setting any seed really confused me.