61 lines
1.7 KiB
Python
61 lines
1.7 KiB
Python
from typing import Callable, Type, TypeVar, Union, cast
|
|
|
|
from reactivex import Observable, abc, defer
|
|
from reactivex import operators as ops
|
|
from reactivex.internal.utils import NotSet
|
|
from reactivex.typing import Accumulator
|
|
|
|
_T = TypeVar("_T")
|
|
_TState = TypeVar("_TState")
|
|
|
|
|
|
def scan_(
|
|
accumulator: Accumulator[_TState, _T], seed: Union[_TState, Type[NotSet]] = NotSet
|
|
) -> Callable[[Observable[_T]], Observable[_TState]]:
|
|
has_seed = seed is not NotSet
|
|
|
|
def scan(source: Observable[_T]) -> Observable[_TState]:
|
|
"""Partially applied scan operator.
|
|
|
|
Applies an accumulator function over an observable sequence and
|
|
returns each intermediate result.
|
|
|
|
Examples:
|
|
>>> scanned = scan(source)
|
|
|
|
Args:
|
|
source: The observable source to scan.
|
|
|
|
Returns:
|
|
An observable sequence containing the accumulated values.
|
|
"""
|
|
|
|
def factory(scheduler: abc.SchedulerBase) -> Observable[_TState]:
|
|
has_accumulation = False
|
|
accumulation: _TState = cast(_TState, None)
|
|
|
|
def projection(x: _T) -> _TState:
|
|
nonlocal has_accumulation
|
|
nonlocal accumulation
|
|
|
|
if has_accumulation:
|
|
accumulation = accumulator(accumulation, x)
|
|
else:
|
|
accumulation = (
|
|
accumulator(cast(_TState, seed), x)
|
|
if has_seed
|
|
else cast(_TState, x)
|
|
)
|
|
has_accumulation = True
|
|
|
|
return accumulation
|
|
|
|
return source.pipe(ops.map(projection))
|
|
|
|
return defer(factory)
|
|
|
|
return scan
|
|
|
|
|
|
__all__ = ["scan_"]
|