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

🎉 withLatestFrom for more than one publisher. #22

Merged

Conversation

jdisho
Copy link
Contributor

@jdisho jdisho commented Apr 11, 2020

I'm working on creating withLatestFrom operators that support more than one publisher.
In RxSwift, I face many scenarios where I need to get the latest values from more than one observable and additionally there is this great thread.

Since under the hood, I'm using combineLatest, I'm supporting as many publishers as the operator supports (up to four).

@freak4pc
Copy link
Member

Hey @jdisho, first of all thank you so much for your work.

TBH I have some issues with adding something like this:

  1. I agree with the thread you linked that this should be a per-project/repo thing because it is a specific constraint of some, but not all, use cases.

  2. The bigger issue is that this tucks in (e.g hides) the fact combineLatest is used under the hood which usually has no weird side-effects but it still quite strange.

I’m all for keeping this issue open to see if there’s more practical interest in adding this, and also to think a bit more if this is a good fit for this library.

Makes sense to you? WDYT?

@jdisho
Copy link
Contributor Author

jdisho commented Apr 11, 2020

Hey @freak4pc, thanks for your explanation. We can leave it open and see if other folks have different opinions. 😄

However, can you elaborate a bit more on your points? B/c, I don't fully understand them. 😇

  1. ... because it is a specific constraint of some, but not all, use cases.

    What can be some other cases where the implementation with combineLatest can be incorrect or have unexpected side effects?

    In an example, don't you always expect on button tap, to get the latest value from publisher1 and publisher2?

    button.tapPublisher.withLatestFrom(publisher1, publisher2)
  2. ... the fact combineLatest is used under the hood which usually has no weird side-effects but it still quite strange.

    Why do you think this is strange? Is this just your personal opinion? Based on this argument, every new operator that reuses given ones under the hood can feel strange. 🙇‍♂️

@jdisho
Copy link
Contributor Author

jdisho commented Apr 11, 2020

What does @jasdev think? 🤓

@freak4pc
Copy link
Member

  1. Yes, some people don't have the use case of combining multiple inputs this way on a button tap. Also the point the original thread makes is that this is very simplistic sugar that is perhaps left explicit given it doesn't provide any "logic" but just basically removes "CombineLatest" from the call-site. These sugar-y operators (IMO) do require thinking over more carefully if they're actually needed.

  2. Of course it's my personal opinion, I can't have anyone else's opinion but my own :)

@jdisho
Copy link
Contributor Author

jdisho commented Apr 11, 2020

IMO, the user of this operator shouldn't care about the implantation details. I think what's important is the operator's description to match the expectations.

If this is an option, we can create WithLatestFrom2 and WithLatestFrom3 without using combineLatest.

@freak4pc
Copy link
Member

Ok, I thought of it some more, I think this could be an OK addition. I'd be happy to get more opinions though.

Comment on lines 40 to 55
/// Upon an emission from self, emit the latest value from the
/// second and third publisher, if any exists.
///
/// - parameter other: A second publisher source.
/// - parameter other1: A third publisher source.
///
/// - returns: A publisher containing the latest value from the second and third publisher, if any.
func withLatestFrom<Other, Other1>(_ other: Other,
_ other1: Other1)
-> AnyPublisher<(Self.Output, Other.Output, Other1.Output), Failure>
where Other: Publisher, Other1: Publisher, Other.Failure == Failure, Other1.Failure == Failure {
let combined = combineLatest(other, other1)
.eraseToAnyPublisher()
return withLatestFrom(combined)
.eraseToAnyPublisher()
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can go down this road:

Suggested change
/// Upon an emission from self, emit the latest value from the
/// second and third publisher, if any exists.
///
/// - parameter other: A second publisher source.
/// - parameter other1: A third publisher source.
///
/// - returns: A publisher containing the latest value from the second and third publisher, if any.
func withLatestFrom<Other, Other1>(_ other: Other,
_ other1: Other1)
-> AnyPublisher<(Self.Output, Other.Output, Other1.Output), Failure>
where Other: Publisher, Other1: Publisher, Other.Failure == Failure, Other1.Failure == Failure {
let combined = combineLatest(other, other1)
.eraseToAnyPublisher()
return withLatestFrom(combined)
.eraseToAnyPublisher()
}
/// Upon an emission from self, emit the latest value from the
/// second and third publisher, if any exists.
///
/// - parameter other: A second publisher source.
/// - parameter other1: A third publisher source.
///
/// - returns: A publisher containing the latest value from the second and third publisher, if any.
func withLatestFrom<Other: Publisher, Other1: Publisher>(_ other: Other,
_ other1: Other1)
-> Publishers.WithLatestFrom<Self,
AnyPublisher<(Other.Output, Other1.Output), Self.Failure>,
(Self.Output, Other.Output, Other1.Output)>
where Other.Failure == Failure, Other1.Failure == Failure {
let combined = other.combineLatest(other1)
.eraseToAnyPublisher()
return withLatestFrom(combined, resultSelector: { ($0, $1.0, $1.1) })
}

@codecov
Copy link

codecov bot commented Apr 12, 2020

Codecov Report

Merging #22 into master will increase coverage by 0.65%.
The diff coverage is 100.00%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master      #22      +/-   ##
==========================================
+ Coverage   96.72%   97.37%   +0.65%     
==========================================
  Files          34       38       +4     
  Lines        1617     2246     +629     
==========================================
+ Hits         1564     2187     +623     
- Misses         53       59       +6     
Impacted Files Coverage Δ
Sources/Operators/WithLatestFrom.swift 93.15% <100.00%> (+1.34%) ⬆️
Tests/WithLatestFromTests.swift 100.00% <100.00%> (ø)
Tests/CreateTests.swift 100.00% <0.00%> (ø)
Sources/Subjects/ReplaySubject.swift 82.35% <0.00%> (ø)
Tests/ShareReplayTests.swift 100.00% <0.00%> (ø)
Sources/Operators/ShareReplay.swift 100.00% <0.00%> (ø)
Tests/ReplaySubjectTests.swift 100.00% <0.00%> (ø)
Sources/Operators/Create.swift 100.00% <0.00%> (+12.50%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 7ed4677...25ba2dc. Read the comment docs.

@jdisho jdisho changed the title [WIP] withLatestFrom for more than one publisher. 🎉 withLatestFrom for more than one publisher. Apr 12, 2020
@jdisho jdisho requested a review from freak4pc April 12, 2020 16:26
Copy link
Member

@freak4pc freak4pc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks great! I literally only have a super-tiny comment, you did a really stellar job on this PR 👏👏👏

Very detail-oriented.

Copy link
Member

@freak4pc freak4pc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh wait, I just realized you're missing README.md updates :)
Mind taking care of those @jdisho ?

@jdisho
Copy link
Contributor Author

jdisho commented Apr 16, 2020

Always forget that! 😄
Yes, I will take care. Thanks for the review.

@freak4pc
Copy link
Member

Do you have time to finish the README here? I'm happy to wrap it for you. Let me know ;)

@jdisho
Copy link
Contributor Author

jdisho commented Apr 19, 2020

Working on it now 🤗

@freak4pc
Copy link
Member

@jdisho jdisho force-pushed the withLatestFrom-many-publishers branch from f52695a to 1826a29 Compare April 19, 2020 11:23
README.md Outdated
@@ -74,9 +74,11 @@ github "CombineCommunity/CombineExt"

This section outlines some of the custom operators CombineExt provides.

### withLatestFrom
## withLatestFrom
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oops?

README.md Outdated
Merges two publishers into a single publisher by combining each value from `self` with the _latest_ value from the second publisher, if any.
### withLatestFrom(_:)

Merges **two** publishers into a single publisher by combining each value from `self` with the _latest_ value from the second publisher, if any.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's not add specific documentation per-overload:)
We should just expand withLatestFrom mentioning it supports overloads of up to 4 observables

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I updated te README based on this comment and I hope I got it right. Should it be fine now? 😄

@jdisho jdisho force-pushed the withLatestFrom-many-publishers branch from 1826a29 to eb08832 Compare April 20, 2020 08:42
Copy link
Member

@freak4pc freak4pc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor note but looks greattt

@freak4pc freak4pc merged commit be7e1d0 into CombineCommunity:master Apr 20, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants