reactive
reactive copied to clipboard
unzip and uneither
For my own project, I had to implement those two methods. I did it on EventStream by the code below. I'm very new to reactive and don't know where to put it in the library, otherwise I would file a pull request.
implicit def eventStreamRich[T](es: EventStream[T]) = new {
def unzip[A,B](implicit ev: T <:< (A,B)): (EventStream[A],EventStream[B]) =
(es.map(t => ev(t)._1), es.map(t => ev(t)._2))
def uneither[A,B](implicit ev: T <:< Either[A,B]): (EventStream[A],EventStream[B]) = (
es.collect{case t if(ev(t).isLeft) => ev(t).left.get},
es.collect{case t if(ev(t).isRight) => ev(t).right.get}
)
}
Nice! The place to put it is in trait EventStream, in reactive-core/src/main/scala/reactive/EventStream.scala. Even though most of its methods are abstract, and implemented in EventSource, in this case it's clearly defined in terms of other methods, so it belongs in EventStream. Please include scaladoc comments, and add a section in reactive-web-demo/src/main/webapp/core/EventStream.html too. Bonus points if you do unzip for Signal too (I think it currently lacks filter, thus collect as well, so that rules out uneither --- unless you want to contribute those too!).
I would like to contribute these, but first two questions:
- What is the desired behavior for a filtered
Signal
? I assume that it would simply not change values when its parent signal changes to a value that the filter does not accept. Maybe other people have other ideas though. - I currently have an open pull request for an unrelated thing. Should I just continue pushing onto my fork (and thereby adding to that pull request) or is there some other thing I should do instead?
On Wed, Apr 17, 2013 at 8:13 PM, Dylan Halperin [email protected]:
I would like to contribute these, but first two questions:
- What is the desired behavior for a filtered Signal? I assume that it would simply not change values when its parent signal changes to a value that the filter does not accept. Maybe other people have other ideas though.
That's one possibility. Another is to use an architecture similar to bacon.js, where behind the scenes (lower-level API) events are not raw values but an ADT of Event[A]. Then a Signal could not have a value. I want to adopt that, but I think in either case filter should do what you described.
- I currently have an open pull request for an unrelated thing. Should I just continue pushing onto my fork (and thereby adding to that pull request) or is there some other thing I should do instead?
Why don't you create a new branch on your fork?
— Reply to this email directly or view it on GitHubhttps://github.com/nafg/reactive/issues/59#issuecomment-16543724 .
as long as a signal always has a value, you cannot filter it. what if the predicate doesn't apply to the initial value?
A few possibilities arise from this.
Filtered stream ignores unaccepted changes
[parent] 1---2---3---4---5---
[evens ] ----2-------4-------
But this is bad because a) it leaves the filtered stream with the possibility of having no initial value and b) it doesn't make a ton of sense in terms of signals.
Filtering a stream results in a Signalof Options
def filter(f: T => Boolean): Signal[Option[T]]
This kind of works, but it's different from the usual semantics of filter
, and that could be confusing.
Signal's value is always optional
Where there exists some ADT for the signal's now
, along the lines of
sealed trait State[+T]
case object Undefined extends State[Nothing]
case class Defined[T](value: T) extends State[T]
And where a filtered signal's parent changed to a value that its filter didn't accept, its own value would go to Undefined
Is this issue superseded by #67? @dylemma, is the discussion about Signal#filter captured somewhere else? It should be on its own issue. Thanks.