Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

zip is not Rx compatible #116

Closed
inamiy opened this issue Mar 26, 2022 · 6 comments
Closed

zip is not Rx compatible #116

inamiy opened this issue Mar 26, 2022 · 6 comments
Labels
duplicate This issue or pull request already exists

Comments

@inamiy
Copy link

inamiy commented Mar 26, 2022

    func test() async throws {
        let now = ContinuousClock.now

        let countUpStream = AsyncTimerSequence(interval: .seconds(0.1), clock: .continuous)
            .map { now.duration(to: $0).components.seconds }
        let countUpStream2 = AsyncTimerSequence(interval: .seconds(0.3), clock: .continuous)
            .map { now.duration(to: $0).components.seconds }

        let zipped = zip(countUpStream, countUpStream2)

        for try await value in zipped {
            print("===> zip", value)
        }
    }

Result:

===> zip (0, 0)
===> zip (0, 0)
===> zip (0, 0)
===> zip (0, 1)
===> zip (1, 1)
===> zip (1, 1)
===> zip (1, 2)
===> zip (2, 2)
===> zip (2, 2)
===> zip (2, 3)
===> zip (3, 3)
===> zip (3, 3)
===> zip (3, 3)
===> zip (3, 4)
===> zip (4, 4)
===> zip (4, 4)
===> zip (4, 5)
===> zip (5, 5)
===> zip (5, 5)
===> zip (5, 6)
===> zip (6, 6)
===> zip (6, 6)
===> zip (6, 6)
===> zip (6, 7)
===> zip (7, 7)
===> zip (7, 7)
===> zip (7, 8)

To Be:

===> zip (0, 0)
===> zip (1, 1)
===> zip (2, 2)
...
@DevAndArtist
Copy link

DevAndArtist commented Mar 27, 2022

I don't think the example is correct. zip operation has nothing to do with the actual equality of the emitted value. If the LHS sequence emits 0 multiple times, it's expected that the zip operation generate the result containing an equal (or less) amount of 0es.

func test_zip() async {
  let a = [1, 1, 2, 2]
  let b = ["a", "b", "c", "d"]
  let expected = Array(zip(a, b))
  let actual = await Array(zip(a.async, b.async))
  XCTAssertEqual(expected, actual)
}

// expected result: [(1, "a"), (1, "b"), (2, "c"), (2, "d")]

The marble diagram from ReactiveX demonstrates this behavior pretty well: https://reactivex.io/documentation/operators/zip.html

@inamiy
Copy link
Author

inamiy commented Mar 27, 2022

@DevAndArtist
zip will need to take time-interval into consideration.
First example shows 0.1 sec and 0.3 sec difference, which are needed to take into account.

@DevAndArtist
Copy link

DevAndArtist commented Mar 27, 2022

I don't understand. AsyncTimerSequences are only the producer sequences and have nothing to do with how zip should behave. The first sequence emits multiple 0ers, so does the second sequence, then zip is just zipping those 0ers together into a bunch of tuples.

--0--0--0---------------------------->
---------0---------0---------0------->

zip
--------(0,0)-----(0,0)------(0,0)--->

zip is only awaiting until each sequence emits at least one new value to perform zipping, nothing more nothing less.

@DevAndArtist
Copy link

DevAndArtist commented Mar 27, 2022

If you need a result that looks more like this:

===> zip (0, 0)
===> zip (1, 1)
===> zip (2, 2)
...

then you'd need to extend both async sequences with something like removeDuplicates().

let zipped = zip(countUpStream.removeDuplicates(), countUpStream2.removeDuplicates())

@inamiy
Copy link
Author

inamiy commented Mar 27, 2022

Ah, my bad. The example was a too complicated (using less than 1 sec interval that causes duplicated same seconds).
After fixing, I noticed other issue so I will close here and start over again.

@inamiy
Copy link
Author

inamiy commented Mar 27, 2022

Added simpler example issue in:

@parkera parkera added the duplicate This issue or pull request already exists label May 4, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
duplicate This issue or pull request already exists
Projects
None yet
Development

No branches or pull requests

3 participants