tindzk / MetaRx

Reactive data structures for Scala and Scala.js
35 stars 13 forks source link

Support for zip() for more than 2 input channels #18

Closed mkotsbak closed 9 years ago

mkotsbak commented 9 years ago

ch1.zip(ch2).zip(ch3) is giving a nested tuple, which is a bit ugly to e.g. match on:

ch1.zip(ch2).zip(ch3).map { case ((ch1Val, ch2Val), ch3Val) => ... }

Instead, zip should allow multiple arguments:

ch1.zip(ch2, ch3) and it should give a triple:

ch1.zip(ch2, ch3).map { case (ch1Val, ch2Val, ch3Val) => ... }

See. also #19

mkotsbak commented 9 years ago

Or maybe support some flattening or flatZip?

tindzk commented 9 years ago

To my knowledge variable-length tuples are not possible. How do other projects solve this?

mkotsbak commented 9 years ago

Hmm, if it isn't, maybe hard coding zip with e.g. 2, 3 and 4 arguments would be a workaround.

mkotsbak commented 9 years ago

For more arguments maybe use a list? It is easy to do matching on a List too. Hmm, but I don't think pattern matching on List is working any good. Intellij says "fruitless type test", List[Any] could also match.

mkotsbak commented 9 years ago

I'm suspecting Slick might have been in this issue, with join/zip. But its monadic joins combined with for expressions I find quite clean.

mkotsbak commented 9 years ago

Hmm, but monadic style is supported:

This: .show(initial.zip(headword).map { case (init, head) => init && head.length == 0})

could be written as:

.show(initial.flatMap(init => headword.is("").map(noHead => noHead && init)))

or the other way around, which proves that the result is dependent on both input values:

.show(headword.is("").flatMap(noHead => initial.map(init => init && noHead)))

and as for expression:

.show( for (init <- initial; noHead <- headword.is("")) yield init && noHead)

or to handle it as zip (contrived example) : .show( for (init <- initial; noHead <- headword.is("")) yield (init, noHead) match {case (true, true) => true; case _ => false} )

which works for n number of combined input values. Examples like this should probably be added to the manual, possibly together with description of zip() (and remove combine()).

mkotsbak commented 9 years ago

Looking at Bacon.js: https://baconjs.github.io/api.html#bacon-combinewith

Combinewith is probably possible to implement in Scala too, with both input channels and arguments to the combining function as varargs?

That being said, I think this won't be any better than JS. The varargs parameters needs to be of type Any.

The array variant is similar to my List suggestion.

mkotsbak commented 9 years ago

Looking into a hardcoded version for 3 arguments.