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

Merge on a collection of observables #579

Closed
joeljeske opened this issue Mar 25, 2016 · 14 comments
Closed

Merge on a collection of observables #579

joeljeske opened this issue Mar 25, 2016 · 14 comments

Comments

@joeljeske
Copy link

From the merge docs here, it would make sense that I could merge a collection of similarly typed observables like the following

let taps: Observable<Void> = [btn1.rx_tap, btn2.rx_tap].merge()

Instead, it appears that it only accepts an observable stream of similarly typed observables.

let taps: Observable<Void> = [btn1.rx_tap, btn2.rx_tap].toObservable().merge()

The toObservable() call seems like unnecessary overhead as the set of observables won't change and is completely known upfront.

Am I missing something or is this how merge() is designed and used throughout all of Rx?

@thanegill
Copy link
Contributor

How's this?

Observable<Void>.of(btn1.rx_tap, btn2.rx_tap).merge()

@joeljeske
Copy link
Author

Its not as much the syntax but the reason why an observable of observables must be created before they can be merged. Why couldn't it be merged exactly at the time of the call instead of as they are emitted?

@kzaher
Copy link
Member

kzaher commented Apr 5, 2016

Hi @joeljeske ,

Observable<Void>.of(btn1.rx_tap, btn2.rx_tap).merge()

... this does give a little more verbosity, but also clarity to the code.

[ob1, ob2].merge()

... is little less clear that it's related with Rx, but not too bad. I'm thinking of maybe creating additional convenience for this since we do have the same for concat.

@LukaJCB
Copy link

LukaJCB commented Jul 28, 2016

Is there any reason why we can't have btn1.rx_tap.merge(btn2.rx_tap) ?

@Dwar3xwar
Copy link

@LukaJCB I think withLatestFrom is a better method to use when combining only two observables so having the merge syntax be similar to that will become unclear. For merge, the design is to combine an much larger size of observables into a single stream.

@LukaJCB
Copy link

LukaJCB commented Aug 4, 2016

@Dwar3xwar correct me if I'm wrong, but doesn't withLatestFrom have completely different semantics? Merge emits if any of the given Observables emit, while withLatestFrom only emits when the first one does.

@kzaher
Copy link
Member

kzaher commented Aug 4, 2016

We'll change this in RxSwift 3.0.

Observable.merge([ob1, ob2])
Observable.concat([ob1, ob2])

and another overloads

ob1.merge(ob2)
ob1.concat(ob2)

This should please everyone I believe.

@guitcastro
Copy link

@kzaher Those overload were added ?

@carlosypunto
Copy link
Contributor

@kzaher I think actually is Observable.from([ob1, ob2]).merge()

@acchou
Copy link

acchou commented Dec 18, 2016

It doesn't look like ob1.merge(ob2) got implemented?

@DivineDominion
Copy link
Contributor

Neither does Observable.of([ob1, ob2]) work, for that matter

@pschneider
Copy link

This combined with the mergeDelayError Operator would be awesome.
http://reactivex.io/documentation/operators/merge.html

Had the first use case where this would've been quite neat today :)

@kzaher
Copy link
Member

kzaher commented Feb 28, 2017

Hi guys,

I've just pushed additional merge operator overloads to develop branch.

The only operator that isn't implemented now is ob1.merge(ob2).

For merge you can now do:

Observable.merge(btn1.rx_tap, btn2.rx_tap)
Observable.merge([btn1.rx_tap, btn2.rx_tap])

The reason why we currently don't plan to support ob1.merge(ob2) is because merge is a symmetrical operation. ob1.merge(ob2) would imply ob1 is somehow different than obs2.

After some discussions with other core contributors, we've decided Observable.merge(btn1.rx_tap, btn2.rx_tap) is enough for the time being.

ob1.concat(ob2) makes sense IMHO because ob1 really comes before ob2 so they don't have a symmetrical relationship.

I'm going to close this issue for now, but feel free to reopen it if there is something wrong.

@kzaher kzaher closed this as completed Feb 28, 2017
@arctouch-marcelogobetti
Copy link

arctouch-marcelogobetti commented Mar 17, 2017

Hi @kzaher , I'm running a playground on RxSwift 3.3.1 and maybe I didn't fully understand this new merge() operator. Please look at these examples, I expected them to behave equally:

let disposeBag = DisposeBag()
let resources = ["a", "b", "c", "d"]
let observables = resources.map { Observable.just($0) }

example("Observable.from([...]).merge()") {
  let observablesFrom = Observable.from(observables)
  let merge = observablesFrom.merge()
  merge.subscribe(onNext: { print($0) }).disposed(by: disposeBag)
  merge.toArray().subscribe(onNext: { print($0) }).disposed(by: disposeBag)
}

example("Observable.merge([...])") {
  let merge = Observable.merge(observables)
  merge.subscribe(onNext: { print($0) }).disposed(by: disposeBag)
  merge.toArray().subscribe(onNext: { print($0) }).disposed(by: disposeBag)
}

example("Observable.from([...]).concat()") {
  let observablesFrom = Observable.from(observables)
  let concat = observablesFrom.concat()
  concat.subscribe(onNext: { print($0) }).disposed(by: disposeBag)
  concat.toArray().subscribe(onNext: { print($0) }).disposed(by: disposeBag)
}

example("Observable.concat([...])") {
  let concat = Observable.concat(observables)
  concat.subscribe(onNext: { print($0) }).disposed(by: disposeBag)
  concat.toArray().subscribe(onNext: { print($0) }).disposed(by: disposeBag)
}

The first merge() example prints the 4 strings: each one on its own onNext, and all of them in a single array when using toArray() - which is what I want. The second merge() example does only print "a" and ["a"]. The concat() examples both work like the first merge() example.
Please ignore the fact that I'm creating several variables, it was just to have a better visualization of the return type on each step.

Thank you in advance and sorry if I'm doing any silliness here!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests