The .NET Reactive Framework (Rx) Enables LINQ over Events
Erik Meijer and Wes Dyer have created the .NET Reactive Framework (Rx), the mathematical dual of LINQ to Objects, allowing programmers to use LINQ over events. Erik and Brian Beckman demonstrate that IObservable is a continuation monad.
Reactive Programming isn’t something new. It’s already used by Cells, a dataflow extension for Common Lisp, or by Trellis, a Python extension supporting high-order reactive programming. In C#, a programmer uses reactive programming whenever he specifies a call-back for an asynchronous operation or a handler for an event. When the asynchronous operation finishes or when the handled event takes place, a method gets called and executed as a reaction to the event.
LINQ over Objects uses the pair of interfaces IEnumerable and IEnumerator to iterate over collections of data. The Enumerator’s MoveNext() method is used to go from one element of the enumeration to the next one, and the Current property is used to retrieve the respective element. This mechanism uses a “pull” process which is simple, well understood and widely used. Erik has discovered that IEnumerable has a dual characteristic: as one can pull a piece of data from a collection, he can also push one into the same collection. This represents another approach to reactive programming.
Theoretically, the IEnumerable interface could be used to add objects to a collection, but it can’t be used in asynchronous operations because it blocks. That’s why the team has introduced a new pair of interfaces: IObservable and IObserver. One can assign an IObserver to a collection of data and subscribe it to an IObservable. When a new data is available, it can be pushed into the collection by passing it to the IObservable, which in turn gives it to IObserver. Jafar Husain, a developer on the Presentation Platform Controls team at Microsoft, explains how the IObserver pattern is used:
To traverse an IObservable you go through the same actions as an IEnumerable but in reverse. You create an IObserver, give it to an IObservable, and the IObservable “pushes” data into the IObserver by invoking its methods. When an IObservable invokes the “OnUpdate” method on an Observer it is equivalent to an IEnumerable method using the yield keyword to give information to an IEnumerable. Similarly when an IObservable invokes the “OnCompleted” method on an Observer it is equivalent to an IEnumerable using the break keyword to indicate that there is no more data.
What is this good for? This approach seems to be great at handling events. One could attach an IObserver to mouse events and record them asynchronously into a collection. Then one can iterate over the data with LINQ, and process it accordingly. To demonstrate its power in handling GUI events, the Rx framework has been used in Silverlight Toolkit Unit Test and it’s been included in its source code, packaged in System.Reactive.dll. It will also be part of .NET 4.0.
Brian Beckman, a software architect and astrophysicist, demonstrates in a video interview with Erik Meijer that IObservable is a continuation monad, the dual of the IEnumerable monad. Erik also shows how the IObservable interface has been constructed by dualizing IEnumerable.
Brandon Holt, Preston Briggs, Luis Ceze, Mark Oskin May 21, 2015
Kai Kreuzer, Olaf Weinmann May 21, 2015