danschultz / frappe

A Dart package for functional reactive programming

Home Page:http://pub.dartlang.org/packages/frappe

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Move transformation methods off of Reactable

danschultz opened this issue · comments

When Reactable has transformation methods, like map, zip, etc, it's unclear what type of Reactable the transformation returns. Moving these methods to Property and EventStream makes it clearer that a transformation of a Property will return another Property.

I think it makes sense to keep the listener methods on Reactable. This includes properties like first and last, and maybe also methods like toList() etc.

One thing to keep in mind is what is the difference between a property and an event stream.
In my mind it is just that properties have a notion of holding on to their current value. Ie that it is a special type of event stream. Does it make sense for property to extend eventstream?

This is a learning journey for me, as such I might be getting this wrong. A property is a value that changes over the lifetime of the application. A stream is a series of events that flow into the system via user input or some other external means. Because of this, I think the concepts are different enough that they shouldn't inherit from one or the other.

What they do have in common is providing a way to respond to their changes. So my thinking is that Reactable will be the interface that you use to listen to Property and EventStream changes. On it will be listen(), forEach(), first, last, etc.

Other approaches I've seen with RxJS and Reactive Cocoa is to just have a Stream type. They make no distinction between streams and properties. However, they do allow you to "replay" the last event. In the case of Reactive Cocoa, this is done by using RACSignal.replayLast() which returns a Signal, which is their name for a stream. However, if you transform a replay stream, I believe the returned stream will not be replayed . So calling signal.replayLast().map((v) => v + 1) returns a non-replaying stream. This is a valid approach, but I feel you lose some ease-of-use.

I definitely agree with your last point that transforming a property should produce another property. Ie if the input stream replays the last value then the transformed one should. This is the most intuitive and useful approach.

I noticed that stream.ext also hasn't hat concept and leaves it all as Stream.

I'm with you in that I prefer a separate class that identifies something as "a stream that replays its current value" and I like the name Property for that even though a separate type isn't strictly needed I guess.

However if you step out a level from how the event streams and properties originate and look at how they differ semantically then is there any more difference than just that properties remember their last value?

Aren't they identical in behavior other than in relation to the current value?

I need to think about this a bit more and also want to take a look at some implementations in languages like Scala and Haskell. I'll draft up a spec and throw it up on the wiki in a week or two.

Pushed some work to the v0.4 branch which includes some changes to the class hierarchy:

  • Reactable now extends from Stream.
  • Reactable now contains all transformation and combinator methods.
  • Property still contains some combinator methods like and(), or(), etc. I'm contemplating removing these methods since they're duplicative of Reactable.combine(), and don't really add much convenience.