ReactiveX / RxPY

ReactiveX for Python

Home Page:https://rxpy.rtfd.io

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Unexpected results of switch_map operator

zhura opened this issue · comments

Describe the bug
I got unexpected results when using switch_map operator.

To Reproduce

import reactivex as rx
from reactivex import operators as ops

obs1 = rx.of(1, 2, 3)
obs2 = rx.of(0.7, 0.8, 0.9, 1.1, 1.4, 2.5, 2.7, 4.5)

obs1.pipe(
    ops.switch_map(lambda t: obs2.pipe(
        ops.last(lambda m: m <= t),
        ops.map(lambda m: (t, m))
    ))
).subscribe(on_next=print)

and I got:

(3, 2.7)

Expected behavior
Expected results (at least I did the same using RxJs):

(1, 0.9)
(2, 1.4)
(3, 2.7)
  • OS - MacOS
  • RxPY version - 4.0.4
  • Python version - 3.9.16

Hi @zhura Thank you for opening this issue;

The switch_map operator only emits from the last emitted inner observable. With rx.of(1,2,3), you are emitting immediately 3 times, hence the inner observables created by 1 and 2 are already ignored by the time the emissions of obs2 start.

Given that your inner observable only emits 1 item (due to "last"), I believe that flat_map instead of switch_map would give you the correct result (the issue is actually within switch_latest, which is used in switch_map) as can be verified by the following test:

def test_issue_699():
    scheduler = TestScheduler()
    obs1 = reactivex.of(1, 2, 3)
    obs2 = reactivex.of(0.7, 0.8, 0.9, 1.1, 1.4, 2.5, 2.7, 4.5)
    observer = scheduler.create_observer()
    obs1.pipe(
        operators.flat_map(
            lambda t: obs2.pipe(
                operators.last(lambda m: m <= t), operators.map(lambda m: (t, m))
            )
        )
    ).subscribe(observer)
    scheduler.start()
    assert observer.messages == [
        on_next(0, (1, 0.9)),
        on_next(0, (2, 1.4)),
        on_next(0, (3, 2.7)),
        on_completed(0),
    ]

Though it does not match RxJS, I don't feel that this is a bug, but happy to hear any further thoughts on your end