FRP is definitely an interesting concept. I believe http://elm-lang.org/ is currently one of the best practical examples of it (haven't used it myself though).
It honestly took some time to write that post, I read a lot of papers to truly understand the origin of FRP and what was the definition of a Reactive System in the 90s'. It was very fun, a lot of math and papers, but worthy.
Sodium looks nice. Personally I like reactive-banana but that's mainly because it's the one I know and because it has more tutorials than Sodium. Unfortunately the FRP ecosystem still seems to still be in such flux that there's no up-to-date information on the differences between the available libraries.
It's interesting to compare the FRP situation in Haskell to that in OCaml. In OCaml there's one major well-documented FRP library (React) and only a few small competitors so the choice is much easier. And where in Haskell FRP libraries don't actually seem to be used much in other packages in OCaml the React library is used in utop (GHCI equivalent / advanced REPL) and the very widely used LWT (cooperative threads) library has special support for working with React.
Could C#'s LINQ be considered a form of reactive programming, considering that everything in LINQ is lazily evaluated? Or is that a similar, but different paradigm?
No. Those are two concepts that are orthogonal to each other.
Lazy evaluation vs strict (non-lazy) evaluation affects when stuff gets computed. Lazyness doesn't really let you do anything you can't do with strict evaluation with one big exception. With lazy evaluation you can handle values that would cause problems (crashes, exceptions or infinite loops) if you were to evaluate them strictly. This is why with LINQ you can operate on an infinite collection of values as long as you only use a finite amount of them.
Lazy evaluation works best with a functional style of programming (LINQ really is a functional mini-language inside C#) as reasoning about what your program does becomes complicated if you combine lazy evaluation with mutation / setting variables. With lazy evaluation it becomes harder to know when a variable gets set and consequently what value a variable has at a given time. I suspect this is why the only popular language that's based on lazy evaluation (Haskell) also strongly discourages mutation.
Reactive programming is about things changing. In particular it's about propagating changes. The typical metaphor is that of a spreadsheet, you change the number in one cell and every cell that refers to the changed cell gets updated. In C# with Rx (reactive extensions) this is modeled through observables, which are really just the plain old observer pattern with some nice abstractions. Rx does use LINQ syntax btw, but don't be confused by that since it works on IObservable (reactive) instead of IEnumerable (lazy).
Reactive programming with observables can be thought of as changing a pull model to a push model. Where with enumerables you request (pull) the next value with an observable you get notified (push) when there's a new value.
The observer pattern is very much based on mutation (because you have to keep the list of observers) and therefore doesn't really work all that well with lazyness. There are other approaches to reactive programming that do, Functional Reactive Programming is a name for a collection of approaches to reactive programming that don't require mutation. Because they don't require mutation they work a lot better with lazyness, in fact most FRP libraries are written in "lazy" Haskell.
The observer pattern is very much based on mutation (because you have to keep the list of observers) and therefore doesn't really work all that well with lazyness.
Exactly and there's one more important thing to remember when dealing with the GoF's definition of the Observer pattern: it's imperative. This means that the value of a variable at the time of evaluation is important, in Reactive Programming this side can be ignored, because state is not anymore a component. The outcome of this is that, when dealing with asynchronous computation, the observer pattern will create what we call "Spaghetti Code" and will crate a lot of troubles. :)
6 comments
2 u/pminten 15 Aug 2015 17:42
FRP is definitely an interesting concept. I believe http://elm-lang.org/ is currently one of the best practical examples of it (haven't used it myself though).
0 u/bontoJR [OP] 16 Aug 2015 15:57
Yes! Another one that looks very promising is Sodium that correctly has a denotational semantics.
It honestly took some time to write that post, I read a lot of papers to truly understand the origin of FRP and what was the definition of a Reactive System in the 90s'. It was very fun, a lot of math and papers, but worthy.
1 u/pminten 16 Aug 2015 18:38
Sodium looks nice. Personally I like reactive-banana but that's mainly because it's the one I know and because it has more tutorials than Sodium. Unfortunately the FRP ecosystem still seems to still be in such flux that there's no up-to-date information on the differences between the available libraries.
It's interesting to compare the FRP situation in Haskell to that in OCaml. In OCaml there's one major well-documented FRP library (React) and only a few small competitors so the choice is much easier. And where in Haskell FRP libraries don't actually seem to be used much in other packages in OCaml the React library is used in utop (GHCI equivalent / advanced REPL) and the very widely used LWT (cooperative threads) library has special support for working with React.
0 u/Xenoprimate 15 Aug 2015 21:58
Could C#'s LINQ be considered a form of reactive programming, considering that everything in LINQ is lazily evaluated? Or is that a similar, but different paradigm?
2 u/pminten 16 Aug 2015 11:28
No. Those are two concepts that are orthogonal to each other.
Lazy evaluation vs strict (non-lazy) evaluation affects when stuff gets computed. Lazyness doesn't really let you do anything you can't do with strict evaluation with one big exception. With lazy evaluation you can handle values that would cause problems (crashes, exceptions or infinite loops) if you were to evaluate them strictly. This is why with LINQ you can operate on an infinite collection of values as long as you only use a finite amount of them.
Lazy evaluation works best with a functional style of programming (LINQ really is a functional mini-language inside C#) as reasoning about what your program does becomes complicated if you combine lazy evaluation with mutation / setting variables. With lazy evaluation it becomes harder to know when a variable gets set and consequently what value a variable has at a given time. I suspect this is why the only popular language that's based on lazy evaluation (Haskell) also strongly discourages mutation.
Reactive programming is about things changing. In particular it's about propagating changes. The typical metaphor is that of a spreadsheet, you change the number in one cell and every cell that refers to the changed cell gets updated. In C# with Rx (reactive extensions) this is modeled through observables, which are really just the plain old observer pattern with some nice abstractions. Rx does use LINQ syntax btw, but don't be confused by that since it works on IObservable (reactive) instead of IEnumerable (lazy).
Reactive programming with observables can be thought of as changing a pull model to a push model. Where with enumerables you request (pull) the next value with an observable you get notified (push) when there's a new value.
The observer pattern is very much based on mutation (because you have to keep the list of observers) and therefore doesn't really work all that well with lazyness. There are other approaches to reactive programming that do, Functional Reactive Programming is a name for a collection of approaches to reactive programming that don't require mutation. Because they don't require mutation they work a lot better with lazyness, in fact most FRP libraries are written in "lazy" Haskell.
0 u/bontoJR [OP] 16 Aug 2015 16:04
Great answer. Just few things to add:
Exactly and there's one more important thing to remember when dealing with the GoF's definition of the Observer pattern: it's imperative. This means that the value of a variable at the time of evaluation is important, in Reactive Programming this side can be ignored, because state is not anymore a component. The outcome of this is that, when dealing with asynchronous computation, the observer pattern will create what we call "Spaghetti Code" and will crate a lot of troubles. :)