• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Tim Cooke
  • Campbell Ritchie
  • Paul Clapham
  • Ron McLeod
  • Liutauras Vilda
Sheriffs:
  • Jeanne Boyarsky
  • Rob Spoor
  • Bear Bibeault
Saloon Keepers:
  • Jesse Silverman
  • Tim Moores
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
Bartenders:
  • Piet Souris
  • Al Hobbs
  • salvin francis

Is Functional Reactive Programming, at its most basic, a combo of Streams and the Observer Pattern?

 
Ranch Hand
Posts: 161
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I've done a little investigation and it seems that, at the core, reactive programming is combining the Functional Programming concepts built into Java 8 (Streams, perhaps closures) and the Observer pattern.
Is this way off base, or too simplistic, or perhaps I've missed the point and need the Functional Reactive Programming book to guide me?
 
Saloon Keeper
Posts: 13401
300
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I haven't really worked with RxJava, but from what I know about it I would say that your observation appears correct.

You can imagine it as streams in Java 8, except streams do something when you ask them to do something, while observables in RxJava do something when data to do something with becomes available.
 
Author
Posts: 12
5
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Lanny,

You are essentially correct, except that "true" FRP includes one more element: It is mathematically compositional. This gives a big scalability advantage, in that the code doesn't become unmanageable as the size and complexity of the program increases. The book is largely about the different way of thinking involved in programming this way: viewing the program as a declarative description of the outputs in terms of the inputs.


Steve
 
Stephan van Hulst
Saloon Keeper
Posts: 13401
300
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Stephen, can you give an example how FRP is mathematically compositional, where Java 8 Streams are not?
 
Stephen Blackheath
Author
Posts: 12
5
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Stephan,

I haven't worked with Java streams but my understanding is that they don't function "asynchronously", by which I mean there is no way to merge the asynchronously occurring values of two streams into one. For example, let's say the values 1, 2, 3 appeared on stream sa. Presumably this limitation would mean that Java streams couldn't be used to implement, say, user interface logic. AFAIK you couldn't do the following in Java streams...



...with the result that sc will either output 1, 10, 2, 20, 3, 30, or it will output 10, 1, 20, 2, 30, 3, or something similar. Please correct me if I'm wrong. RxJava and Sodium both have this operation.

Sodium, being "true" FRP guarantees compositionality, while RxJava doesn't.

With RxJava you will get one of the two answers above, but which one is a matter of implementation detail, which is not specified.

The definition of compositionality is that the meaning of the composition depends only on the meaning of the components, and the rules used to combine them. Unspecified implementation details or other extraneous factors beyond that line of code have no effect.

In Sodium:
The meaning of sa is a stream of integers.
The meaning of sb is that it is identical to sa except for a modification of each value.
The rule "merge" says that the output stream will be based on the values of the two input streams, but in Sodium, there is a rule about what happens in the case where values are simultaneous. When at a given instant in time, only one of the streams produces a value, the output stream should simply output that value. But, Sodium makes the caller decide what to do in the simultaneous case. For example, we might add simultaneous numbers together:



The output would be 11, 22, 33.

Or, we could say that the value from stream a takes precedence:



The output would be 1, 2, 3. Sodium defines .orElse(..) as a shorthand for this common case.

Compositionality gives huge practical advantages and is easy to achieve in an implementation. Why wouldn't you want it? If you're going to build something huge, shouldn't it be on a solid foundation? I think the reason is that people don't understand the importance of compositionality.


Steve
 
Stephan van Hulst
Saloon Keeper
Posts: 13401
300
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
It's true that Java streams currently don't have a convenient way to merge or "zip" two of them, which is a huge pain when trying to solve certain problems functionally. It is possible however to implement such an operation, and indeed I have done so in the past. This made it possible to do the following:

Your example however highlights two big limitations: 1) This operation only has a well-defined result if the streams involved are "ordered" and 2) streams cannot be reused after you apply an operator to them:

While I would argue that requiring an ordered stream is only fair, I will concede that the lack of reusability of stream instances makes it difficult to compose larger components out of them.

Now I'm curious, how do most FRP implementations deal with reusing observables? Are previously seen values recomputed from the source, or are intermediate computations buffered somewhere?
 
Stephen Blackheath
Author
Posts: 12
5
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Stephan,

Classic FRP is designed with an assumption that all values are associated with a time. In the terminology of Reactive Extensions, this means that it only has hot observables. At the time when you start using an FRP object, there is no access to anything from the past.

Reactive Extensions invented the idea of cold observables, that is, using an FRP-like interface to implement something equivalent to lazy lists in functional programming. FRP came from the world of functional programming, so it didn't need any of this because functional languages have lazy lists already.


Steve
 
Stephan van Hulst
Saloon Keeper
Posts: 13401
300
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thanks for your comments Stephen!
 
Lanny Gilbert
Ranch Hand
Posts: 161
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thanks to both of you for this discussion. I have learned a lot, and wish to continue my learning by checking out Stephen's book.
 
reply
    Bookmark Topic Watch Topic
  • New Topic