Category theory, Monads, and Duality in the world of (BIG) DataBart J.F. De Smetbartde@microsoft.comCloud Programmability Team
What’s in a name?Cloud Programmability TeamLogical role:Research-oriented teamCollaboration with MSRPhysical placement:Oasis within the product teamClose to the SQL Server business(Dual) 80/20 rule of successPortfolioLanguage Integrated Query (LINQ)XML literals in Visual Basic 9Reactive Extensions (Rx)Various undisclosed projectsDemocratizing the cloud
Take OneDemocratizing data access with LINQ
A quick reminder on LINQSolving the impedance mismatch between objects and data through querying.
Back to the future5+ years agoCensored
Democratizing data accessvarres = from p inctx.Productswherep.UnitPrice > 100group p byp.Categoryinto gselectnew { Category = g.Key, Avg = g.Average() };“Lost in translation”varres = ctx.Products          .Where(p => p.UnitPrice > 100)          .GroupBy(p => p.Category)          .Select(g => new { Category = g.Key, Avg = g.Average() });(In-memory) iteratorsQuery providers
C# 3.0 compilation to C# 2.0
Language Integrated MonadsIEnumerable<T>IQueryable<T>IEnumerable<R> SelectMany<T, R>(this IEnumerable<T> source,Func<T, IEnumerable<R>> selector)SelectMany
Maybe baby!BillionNull-propagating dotstring s = name?.ToUpper();Syntactic          sugarname.SelectMany(    _ => _.ToUpper(),    s => s)from _ in namefrom s in _.ToUpper()select sCompilerCan useextension method
Closing the loopLINQ to Haskell 
Take twoDemocratizing event processing with Rx
Once upon a time…Tier splitting“LINQ to Events”
Reactive Extensions (Rx)GPSRSS      feedsStock tickersSocialmediaUI eventsServer management
Pull-based data accessinterfaceIEnumerable<out T>{IEnumerator<T> GetEnumerator();}interfaceIEnumerator<out T> : IDisposable{boolMoveNext();    T      Current { get; }void   Reset();}You could get stuck
Duality in the world around us(Or… the Dutch are cheap)Electricity:  inductor and capacitorLogic:  De Morgan’s LawProgramming?¬𝐴∨𝐵≡¬𝐴∧¬𝐵 ¬𝐴∧𝐵≡¬𝐴∨¬𝐵 
Duality as the secret sauce?Give me a recipehttp://en.wikipedia.org/wiki/Dual_(category_theory)Reversing arrows…Input becomes output and vice versaMaking a U-turnin synchrony
Distilling the essenceProperties and unchecked exceptionsinterfaceIEnumerable<out T>{IEnumerator<T> GetEnumerator();}interfaceIEnumerator<out T> : IDisposable{boolMoveNext();    T      Current { get; }}
Distilling the essenceProperties and unchecked exceptionsinterfaceIEnumerable<out T>{IEnumerator<T> GetEnumerator();}interfaceIEnumerator<out T> : IDisposable{boolMoveNext() throwsException;    T      GetCurrent();}
Distilling the essenceEmbracing a (more) functional styleinterfaceIEnumerable<out T>{IEnumerator<T> GetEnumerator();}interfaceIEnumerator<out T> : IDisposable{boolMoveNext() throwsException;    T      GetCurrent();}
Distilling the essenceEmbracing a (more) functional styleinterfaceIEnumerable<out T>{IEnumerator<T> GetEnumerator();}interfaceIEnumerator<out T> : IDisposable{    (void | T | Exception) MoveNext();}() -> (() -> (void | T | Exception))
Flipping the arrowsPurely mechanical transformation() -> (() -> (void | T | Exception))((void | T | Exception) -> ()) -> ()
Harvesting the resultSo far for abstract nonsenseinterfaceIBar<out T>{voidQux(IFoo<T> foo);}interfaceIFoo<in T>{voidWibble();    void Wobble(T value);    voidWubble(Exception error);}
Harvesting the resultThe observer pattern in disguiseinterfaceIObservable<out T>{void Subscribe(IObserver<T> observer);}interfaceIObserver<in T>{voidOnCompleted();    voidOnNext(T value);    voidOnError(Exception error);}
The observer pattern revisitedStateful!
Interface hierarchyinterfaceIObservable<out T>{IDisposableSubscribe(IObserver<T> observer);}
Message grammarOnNext(42)OnNext(43)OnCompletedsource1OnNext(“Hello”)OnError(error)source2OnNext* [OnError | OnCompleted]
Observable.Create<T> operatorIObservable<int> o = Observable.Create<int>(observer => {  // Assume we introduce concurrency (see later)…observer.OnNext(42);observer.OnCompleted();return () => { /* unsubscribe action */ };});IDisposable subscription = o.Subscribe(onNext:      x  => { Console.WriteLine("Next: " + x); },onError:     ex => { Console.WriteLine("Oops: " + ex); },onCompleted: () => { Console.WriteLine("Done"); });C# doesn’t have anonymous interface implementation, so we provide various extension methods that take lambdas.C# 4.0 named parameter syntax
Observable.Create<T> operatorIObservable<int> o = Observable.Create<int>(observer => {// Assume we introduce concurrency (see later)…observer.OnNext(42);observer.OnCompleted();return () => { /* unsubscribe action */ };});IDisposable subscription = o.Subscribe(onNext:      x  => { Console.WriteLine("Next: " + x); },onError:     ex => { Console.WriteLine("Oops: " + ex); },onCompleted: () => { Console.WriteLine("Done"); });Thread.Sleep(30000); // Main thread is blocked…F10
Observable.Create<T> operatorIObservable<int> o = Observable.Create<int>(observer => {// Assume we introduce concurrency (see later)…observer.OnNext(42);observer.OnCompleted();return () => { /* unsubscribe action */ };});IDisposable subscription = o.Subscribe(onNext:      x  => { Console.WriteLine("Next: " + x); },onError:     ex => { Console.WriteLine("Oops: " + ex); },onCompleted: () => { Console.WriteLine("Done"); });Thread.Sleep(30000); // Main thread is blocked…F10
Observable.Create<T> operatorIObservable<int> o = Observable.Create<int>(observer => {  // Assume we introduce concurrency (see later)…observer.OnNext(42);observer.OnCompleted();return () => { /* unsubscribe action */ };});IDisposable subscription = o.Subscribe(onNext:      x  => { Console.WriteLine("Next: " + x); },onError:     ex => { Console.WriteLine("Oops: " + ex); },onCompleted: () => { Console.WriteLine("Done"); });Thread.Sleep(30000); // Main thread is blocked…F5
Observable.Create<T> operatorIObservable<int> o = Observable.Create<int>(observer => {  // Assume we introduce concurrency (see later)…observer.OnNext(42);observer.OnCompleted();return () => { /* unsubscribe action */ };});IDisposable subscription = o.Subscribe(onNext:      x  => { Console.WriteLine("Next: " + x); },onError:     ex => { Console.WriteLine("Oops: " + ex); },onCompleted: () => { Console.WriteLine("Done"); });Thread.Sleep(30000); // Main thread is blocked…Breakpoint got hit
Iterators dualizedIObservable<int> GetXs() {returnObservable.Create(o =>for(int i = 0;      i < 10;    i++)o.OnNext(i * i);o.OnCompleted();  );}GetXs().Subscribe(x => {Console.WriteLine(x);});IEnumerable<int> GetXs() { for (int i = 0;        i < 10;        i++)yieldreturni * i;yield break;}foreach(var x inGetXs()) {Console.WriteLine(x);}SynchronousAsynchronous
Compositionality mattersIObservable<T>Merge<T>(thisIObservable<T> left,IObservable<T> right){return Create<T>(observer => {// Ignoring a few details for OnCompletedvar d1 = left.Subscribe(observer);var d2 = right.Subscribe(observer);returnnewCompositeDisposable(d1, d2);    });}Lazy evaluation
Bridging Rx with the WorldWhy .NET events aren’t first-class…Hidden data sourceHow to pass around?form1.MouseMove+= (sender, args) => {if(args.Location.X==args.Location.Y)// I’d like to raise another event};form1.MouseMove -=/* what goes here? */Lack of compositionResource maintenance?
Bridging Rx with the World…but observable sequences are first-classSource of Point valuesObjects can be passedIObservable<Point>mouseMoves= Observable.FromEvent(frm, "MouseMove");varfiltered = mouseMoves.Where(pos => pos.X == pos.Y);varsubscription = filtered.Subscribe(…);subscription.Dispose();Can define operatorsResource maintenance!
Composition and QueryingIt’s the continuation monad!// IObservable<string> from TextChanged eventsvarchanged = Observable.FromEvent(txt, "TextChanged");var input = (from e in changedlet text = ((TextBox)e.Sender).Textwheretext.Length >= 3select text)            .DistinctUntilChanged()            .Throttle(TimeSpan.FromSeconds(1));// Bridge with the dictionary web servicevar svc = newDictServiceSoapClient();var lookup = Observable.FromAsyncPattern<string, DictionaryWord[]>                                 (svc.BeginLookup, svc.EndLookup);// Compose both sources using SelectManyvar res = from term in inputfrom words in lookup(term)select words;input.SelectMany(term => lookup(term))
Introducing schedulersHow to be asynchronous?Different ways to Introduce of concurrencyParameterization by schedulersinterfaceIScheduler{DateTimeOffset Now { get; }IDisposableSchedule<T>(       T state,Func<IScheduler, T, IDisposable> f);// Overloads for time-based scheduling}
Example: creation operatorsstatic classObservable{static IObservable<T> Return<T>(T value,IScheduler scheduler)    {return Create<T>(observer =>       {var state = new { value, observer };returnscheduler.Schedule(state, (self, s) =>           {s.observer.OnNext(s.value);s.observer.OnCompleted();            });        });    }}ResourcemgmtAvoiding closures(serialization)
Operational layering
IQbservable<T>LINQ to TwitterHow?ToQbservableTranslatable(Expression trees)IQueryable<T>LINQ to SQLToQueryableLINQ to *.*AsObservableHomo-iconicAsEnumerableAsQbservableAsQueryableToObservableIEnumerable<T>LINQ to ObjectsIObservable<T>LINQ to EventsFixed(MSIL)ToEnumerablePull(interactive)Push(reactive)What?DualityConcurrency(IScheduler)Where?Message loopsDistributedWorker poolsThreads
Take THREEDemocratizing cloud data processing with CoSQL
NoSQL is CoSQL!
The NoSQL trend
Object graphsvar_1579124585 = newProduct{    Title = “The Right Stuff”,  Author = “Tom Wolfe”,    Year = 1979, Pages = 304,    Keywords = new[] { “Book”, “Hardcover”, “American” },    Ratings = new[] { “****”, “4 stars” },};var Products = new[] { _1579124585 };
Queries over object graphsvarq = from product in Productswhereproduct.Ratings.Any(rating => rating == “****”)selectnew { product.Title, product.Keywords };
The O/R paradoxObjectsFully compositional  value ::= scalar            new {…, name = value, … }TablesNon compositional  value ::= new {…, name = scalar, … }
Relational (de)normalization
Queries over tablesvar q = from product in Productsfromrating in Ratingswhereproduct.ID == rating.ProductId           && rating == “****”fromkeyword in Keywordswhereproduct.ID == keyword.ProductIDselectnew { product.Title, keyword.Keyword };varq = from product inProductsjoinrating in Ratingsonproduct.ID equalsrating.ProductIdwhererating == “****”selectproduct intoFourStarProductsfromfourstarproductinFourStarProductsjoinkeyword in Keywordsonproduct.ID equalskeyword.ProductIDselectnew { product.Title, keyword.Keyword };
Welcome to O/R voodoovarq = from product in Productswhereproduct.Ratings.Any(rating => rating == “****”)selectnew { product.Title, product.Keywords };
What did we gain?Ad-hoc queries?But what about scale…The relational Gods invented indexesGoing against the PK-FK flow…from p1 in WWWfrom p2 in WWWwhere p2.Contains(p1.URL)selectnew { p1, p2 };
Job security?
Spot the difference
Duality to the rescue again?
Consequences of duality
More work in the area
Thank you!Bart J.F. De Smetbartde@microsoft.comCloud Programmability Team

Category theory, Monads, and Duality in the world of (BIG) Data

  • 1.
    Category theory, Monads,and Duality in the world of (BIG) DataBart J.F. De Smetbartde@microsoft.comCloud Programmability Team
  • 2.
    What’s in aname?Cloud Programmability TeamLogical role:Research-oriented teamCollaboration with MSRPhysical placement:Oasis within the product teamClose to the SQL Server business(Dual) 80/20 rule of successPortfolioLanguage Integrated Query (LINQ)XML literals in Visual Basic 9Reactive Extensions (Rx)Various undisclosed projectsDemocratizing the cloud
  • 3.
  • 4.
    A quick reminderon LINQSolving the impedance mismatch between objects and data through querying.
  • 5.
    Back to thefuture5+ years agoCensored
  • 6.
    Democratizing data accessvarres= from p inctx.Productswherep.UnitPrice > 100group p byp.Categoryinto gselectnew { Category = g.Key, Avg = g.Average() };“Lost in translation”varres = ctx.Products .Where(p => p.UnitPrice > 100) .GroupBy(p => p.Category) .Select(g => new { Category = g.Key, Avg = g.Average() });(In-memory) iteratorsQuery providers
  • 7.
  • 8.
    Language Integrated MonadsIEnumerable<T>IQueryable<T>IEnumerable<R>SelectMany<T, R>(this IEnumerable<T> source,Func<T, IEnumerable<R>> selector)SelectMany
  • 9.
    Maybe baby!BillionNull-propagating dotstrings = name?.ToUpper();Syntactic sugarname.SelectMany( _ => _.ToUpper(), s => s)from _ in namefrom s in _.ToUpper()select sCompilerCan useextension method
  • 10.
    Closing the loopLINQto Haskell 
  • 11.
    Take twoDemocratizing eventprocessing with Rx
  • 12.
    Once upon atime…Tier splitting“LINQ to Events”
  • 13.
    Reactive Extensions (Rx)GPSRSS feedsStock tickersSocialmediaUI eventsServer management
  • 14.
    Pull-based data accessinterfaceIEnumerable<outT>{IEnumerator<T> GetEnumerator();}interfaceIEnumerator<out T> : IDisposable{boolMoveNext(); T Current { get; }void Reset();}You could get stuck
  • 15.
    Duality in theworld around us(Or… the Dutch are cheap)Electricity: inductor and capacitorLogic: De Morgan’s LawProgramming?¬𝐴∨𝐵≡¬𝐴∧¬𝐵 ¬𝐴∧𝐵≡¬𝐴∨¬𝐵 
  • 16.
    Duality as thesecret sauce?Give me a recipehttp://en.wikipedia.org/wiki/Dual_(category_theory)Reversing arrows…Input becomes output and vice versaMaking a U-turnin synchrony
  • 17.
    Distilling the essencePropertiesand unchecked exceptionsinterfaceIEnumerable<out T>{IEnumerator<T> GetEnumerator();}interfaceIEnumerator<out T> : IDisposable{boolMoveNext(); T Current { get; }}
  • 18.
    Distilling the essencePropertiesand unchecked exceptionsinterfaceIEnumerable<out T>{IEnumerator<T> GetEnumerator();}interfaceIEnumerator<out T> : IDisposable{boolMoveNext() throwsException; T GetCurrent();}
  • 19.
    Distilling the essenceEmbracinga (more) functional styleinterfaceIEnumerable<out T>{IEnumerator<T> GetEnumerator();}interfaceIEnumerator<out T> : IDisposable{boolMoveNext() throwsException; T GetCurrent();}
  • 20.
    Distilling the essenceEmbracinga (more) functional styleinterfaceIEnumerable<out T>{IEnumerator<T> GetEnumerator();}interfaceIEnumerator<out T> : IDisposable{ (void | T | Exception) MoveNext();}() -> (() -> (void | T | Exception))
  • 21.
    Flipping the arrowsPurelymechanical transformation() -> (() -> (void | T | Exception))((void | T | Exception) -> ()) -> ()
  • 22.
    Harvesting the resultSofar for abstract nonsenseinterfaceIBar<out T>{voidQux(IFoo<T> foo);}interfaceIFoo<in T>{voidWibble(); void Wobble(T value); voidWubble(Exception error);}
  • 23.
    Harvesting the resultTheobserver pattern in disguiseinterfaceIObservable<out T>{void Subscribe(IObserver<T> observer);}interfaceIObserver<in T>{voidOnCompleted(); voidOnNext(T value); voidOnError(Exception error);}
  • 24.
    The observer patternrevisitedStateful!
  • 25.
  • 26.
  • 27.
    Observable.Create<T> operatorIObservable<int> o= Observable.Create<int>(observer => { // Assume we introduce concurrency (see later)…observer.OnNext(42);observer.OnCompleted();return () => { /* unsubscribe action */ };});IDisposable subscription = o.Subscribe(onNext: x => { Console.WriteLine("Next: " + x); },onError: ex => { Console.WriteLine("Oops: " + ex); },onCompleted: () => { Console.WriteLine("Done"); });C# doesn’t have anonymous interface implementation, so we provide various extension methods that take lambdas.C# 4.0 named parameter syntax
  • 28.
    Observable.Create<T> operatorIObservable<int> o= Observable.Create<int>(observer => {// Assume we introduce concurrency (see later)…observer.OnNext(42);observer.OnCompleted();return () => { /* unsubscribe action */ };});IDisposable subscription = o.Subscribe(onNext: x => { Console.WriteLine("Next: " + x); },onError: ex => { Console.WriteLine("Oops: " + ex); },onCompleted: () => { Console.WriteLine("Done"); });Thread.Sleep(30000); // Main thread is blocked…F10
  • 29.
    Observable.Create<T> operatorIObservable<int> o= Observable.Create<int>(observer => {// Assume we introduce concurrency (see later)…observer.OnNext(42);observer.OnCompleted();return () => { /* unsubscribe action */ };});IDisposable subscription = o.Subscribe(onNext: x => { Console.WriteLine("Next: " + x); },onError: ex => { Console.WriteLine("Oops: " + ex); },onCompleted: () => { Console.WriteLine("Done"); });Thread.Sleep(30000); // Main thread is blocked…F10
  • 30.
    Observable.Create<T> operatorIObservable<int> o= Observable.Create<int>(observer => { // Assume we introduce concurrency (see later)…observer.OnNext(42);observer.OnCompleted();return () => { /* unsubscribe action */ };});IDisposable subscription = o.Subscribe(onNext: x => { Console.WriteLine("Next: " + x); },onError: ex => { Console.WriteLine("Oops: " + ex); },onCompleted: () => { Console.WriteLine("Done"); });Thread.Sleep(30000); // Main thread is blocked…F5
  • 31.
    Observable.Create<T> operatorIObservable<int> o= Observable.Create<int>(observer => { // Assume we introduce concurrency (see later)…observer.OnNext(42);observer.OnCompleted();return () => { /* unsubscribe action */ };});IDisposable subscription = o.Subscribe(onNext: x => { Console.WriteLine("Next: " + x); },onError: ex => { Console.WriteLine("Oops: " + ex); },onCompleted: () => { Console.WriteLine("Done"); });Thread.Sleep(30000); // Main thread is blocked…Breakpoint got hit
  • 32.
    Iterators dualizedIObservable<int> GetXs(){returnObservable.Create(o =>for(int i = 0; i < 10; i++)o.OnNext(i * i);o.OnCompleted(); );}GetXs().Subscribe(x => {Console.WriteLine(x);});IEnumerable<int> GetXs() { for (int i = 0; i < 10; i++)yieldreturni * i;yield break;}foreach(var x inGetXs()) {Console.WriteLine(x);}SynchronousAsynchronous
  • 33.
    Compositionality mattersIObservable<T>Merge<T>(thisIObservable<T> left,IObservable<T>right){return Create<T>(observer => {// Ignoring a few details for OnCompletedvar d1 = left.Subscribe(observer);var d2 = right.Subscribe(observer);returnnewCompositeDisposable(d1, d2); });}Lazy evaluation
  • 34.
    Bridging Rx withthe WorldWhy .NET events aren’t first-class…Hidden data sourceHow to pass around?form1.MouseMove+= (sender, args) => {if(args.Location.X==args.Location.Y)// I’d like to raise another event};form1.MouseMove -=/* what goes here? */Lack of compositionResource maintenance?
  • 36.
    Bridging Rx withthe World…but observable sequences are first-classSource of Point valuesObjects can be passedIObservable<Point>mouseMoves= Observable.FromEvent(frm, "MouseMove");varfiltered = mouseMoves.Where(pos => pos.X == pos.Y);varsubscription = filtered.Subscribe(…);subscription.Dispose();Can define operatorsResource maintenance!
  • 37.
    Composition and QueryingIt’sthe continuation monad!// IObservable<string> from TextChanged eventsvarchanged = Observable.FromEvent(txt, "TextChanged");var input = (from e in changedlet text = ((TextBox)e.Sender).Textwheretext.Length >= 3select text) .DistinctUntilChanged() .Throttle(TimeSpan.FromSeconds(1));// Bridge with the dictionary web servicevar svc = newDictServiceSoapClient();var lookup = Observable.FromAsyncPattern<string, DictionaryWord[]> (svc.BeginLookup, svc.EndLookup);// Compose both sources using SelectManyvar res = from term in inputfrom words in lookup(term)select words;input.SelectMany(term => lookup(term))
  • 38.
    Introducing schedulersHow tobe asynchronous?Different ways to Introduce of concurrencyParameterization by schedulersinterfaceIScheduler{DateTimeOffset Now { get; }IDisposableSchedule<T>( T state,Func<IScheduler, T, IDisposable> f);// Overloads for time-based scheduling}
  • 39.
    Example: creation operatorsstaticclassObservable{static IObservable<T> Return<T>(T value,IScheduler scheduler) {return Create<T>(observer => {var state = new { value, observer };returnscheduler.Schedule(state, (self, s) => {s.observer.OnNext(s.value);s.observer.OnCompleted(); }); }); }}ResourcemgmtAvoiding closures(serialization)
  • 40.
  • 41.
    IQbservable<T>LINQ to TwitterHow?ToQbservableTranslatable(Expressiontrees)IQueryable<T>LINQ to SQLToQueryableLINQ to *.*AsObservableHomo-iconicAsEnumerableAsQbservableAsQueryableToObservableIEnumerable<T>LINQ to ObjectsIObservable<T>LINQ to EventsFixed(MSIL)ToEnumerablePull(interactive)Push(reactive)What?DualityConcurrency(IScheduler)Where?Message loopsDistributedWorker poolsThreads
  • 42.
    Take THREEDemocratizing clouddata processing with CoSQL
  • 43.
  • 44.
  • 45.
    Object graphsvar_1579124585 =newProduct{ Title = “The Right Stuff”, Author = “Tom Wolfe”, Year = 1979, Pages = 304, Keywords = new[] { “Book”, “Hardcover”, “American” }, Ratings = new[] { “****”, “4 stars” },};var Products = new[] { _1579124585 };
  • 46.
    Queries over objectgraphsvarq = from product in Productswhereproduct.Ratings.Any(rating => rating == “****”)selectnew { product.Title, product.Keywords };
  • 47.
    The O/R paradoxObjectsFullycompositional value ::= scalar new {…, name = value, … }TablesNon compositional value ::= new {…, name = scalar, … }
  • 48.
  • 49.
    Queries over tablesvarq = from product in Productsfromrating in Ratingswhereproduct.ID == rating.ProductId && rating == “****”fromkeyword in Keywordswhereproduct.ID == keyword.ProductIDselectnew { product.Title, keyword.Keyword };varq = from product inProductsjoinrating in Ratingsonproduct.ID equalsrating.ProductIdwhererating == “****”selectproduct intoFourStarProductsfromfourstarproductinFourStarProductsjoinkeyword in Keywordsonproduct.ID equalskeyword.ProductIDselectnew { product.Title, keyword.Keyword };
  • 50.
    Welcome to O/Rvoodoovarq = from product in Productswhereproduct.Ratings.Any(rating => rating == “****”)selectnew { product.Title, product.Keywords };
  • 51.
    What did wegain?Ad-hoc queries?But what about scale…The relational Gods invented indexesGoing against the PK-FK flow…from p1 in WWWfrom p2 in WWWwhere p2.Contains(p1.URL)selectnew { p1, p2 };
  • 52.
  • 53.
  • 54.
    Duality to therescue again?
  • 55.
  • 56.
    More work inthe area
  • 57.
    Thank you!Bart J.F.De Smetbartde@microsoft.comCloud Programmability Team

Editor's Notes

  • #28 Speaker tips:So far, we’ve seen specific operators to create new observable sequencesLike preprogrammed (parameterized) implementations of the IObservable&lt;T&gt; interfaceSometimes we just want to implement the interfaceCan be simplified using Create (general pattern in Rx)Is really the Subscribe method as a lambdaSlide omits what the lambda should return, an Action delegate that’s used to create the IDisposable that’s returned…There’s also CreateWithDisposableWe chose to omit this from the slide (and be imprecise) to focus on the flow of data hereTypically, an observable creates concurrency upon subscription in order to send out the messagesMention this but refer till later, where we mention ISchedulerAlso notice the use of a Subscribe extension methodAgain… this shows how to mimic anonymous interface implementations that C# lacks
  • #29 Speaker tips:Assume we’re in the debuggerSet a breakpoint on the onNext lambda bodyStart the program using F10Now let’s see what Subscribe will do…
  • #30 Speaker tips:Slide is just here for animation of F10Press F10 againSubscribe will new up an IObserver&lt;int&gt; objectThis will get passed to the Create method’s lambda parameter as the “observer” parameter
  • #31 Speaker tips:Emphasize the asynchronous nature of SubscribeMain thread has moved on beyond the asynchronous Subscribe callStill assume the body of create has introduced concurrencyi.e. calls to OnNext and OnCompleted are scheduled to happen in the backgroundWe’ll let the debugger go using F5 to see our breakpoint getting hit
  • #32 Speaker tips:Bang – the breakpoint got hit!Notice where the main thread sits, indicated in grayThough we’re blocking that thread in the sample, it could be doing other useful work……while the observable notifies us about data being availableThis shouldn’t be new to the audienceE.g. when using += (o, e) =&gt; {…} to set up an event handlerSyntactical location of a breakpoint can belong to a whole different thread compared to code close-by!
  • #35 Speaker tips:Big message:Primitive constructor operators are great, but we’d like to do something of more interest…Rx doesn’t aim at replacing existing sources of asynchrony in the frameworkInstead we can bridge with those worldsFirst common source of asynchrony are .NET eventsSuffer from some problems:Nobody thinks of a mouse as a database of pointsMouse database is not “preprogrammed” (like: “give me a mouse that can move once across the screen”) but is an infinite sourceHave to dot into the EventArgs object to obtain the data (sometimes it isn’t even there!)Events cannot be grabbedNo objects that can be passed to a method, stored in a field, put in an array, etc.How’d you write a GPS visualizer that expects to get passed an event producing points? Can’t pass a .NET event along!Composition suffersEveryone has to write logic in event handlers, e.g. an if to filterCan’t hire a mathematician to write a generic filter that works with all eventsAlso, we’d like a filtered event still to be an event (stay in the same “world”)  we have to settle for procedural code todayResource maintenance requires stateHave to remember what you gave to += in order to get rid of it using -=  use a field?Same C# code passed to -= won’t work (there is no value equality between delegates based on what code they contain)Notice resource management gets even harder in the face of compositionSay that applying a hypothetical generic filter to an event gives you a new event “object”Now if you unhook a handler from the filtered event, you want it to unhook from the original event Cascading effect with lots of state maintenance!
  • #37 Speaker tips:How does Rx improve on this?FromEvent methods here reflective overload being usedNotice: omits a few things…Generic parameter for EventArgsFact it returns an IObservable&lt;IEvent&lt;…&gt;&gt;  correct this in the demoRationale: focus on the essence hereComparison to before:Look at the type to see the (no longer hidden) data source  source of Point values (thanks to generics)Objects a la IObservable&lt;Point&gt; can be passed, e.g. to our GPS visualizerJust like LINQ to Objects does, we can define operators on objects  compositionality enters the pictureResource maintenance can be done using a “subscription handle”Yes, you still need to store it somewhere, but you don’t need to remember what you gave itThe old world is like subscribing to a magazine but keeping your hands on the check so you can take it back!In the new world you get an unsubscription card (the Dispose method) you can send in to unsubscribe…Notice state maintenance for unsubscription can be encapsulated now tooE.g. Merge operator that merges n number of observable sequences into oneSubscription causes a subscribe on all of the sequencesUnsubscribe should unsubscribe from all of the underlying sequencesNeeds a list of IDisposable objects  we have an algebra over IDisposable in System.DisposablesCan hide those from the outside world!