Entries:
Comments:
Posts:

Loading User Information from Channel 9

Something went wrong getting user information from Channel 9

Latest Achievement:

Loading User Information from MSDN

Something went wrong getting user information from MSDN

Visual Studio Achievements

Latest Achievement:

Loading Visual Studio Achievements

Something went wrong getting the Visual Studio Achievements

Expert to Expert: Brian Beckman and Erik Meijer - Inside the .NET Reactive Framework (Rx)

Download

Right click “Save as…”

  • High Quality WMV (PC)
  • MP3 (Audio only)
  • MP4 (iPhone, Android)
  • Mid Quality WMV (Lo-band, Mobile)
  • WMV (WMV Video)
Erik Meijer and team (developer Wes Dyer, in particular) have created a profound and beautiful .NET library that will take managed event based programming to new levels. Of course, many of you wish that you could write LINQ expressions over events. Well, now you can thanks to Erik's and Wes Dyer's latest creation, Rx - .NET Reactive Framework. Erik, being a fundamentalist functional theoritician, can't create new programming abstractions without employing some form of monadic magic. 

Enter astrophysicist and monadic composition wizard Brian Beckman. The last time Brian was on C9 he taught us about the State Monad. At the end of that discussion he mentioned he wanted to teach us about the Continuation Monad next. So, who better to conduct this episode of Expert to Expert than Dr. Beckman? Yep. You guessed it! Rx employs the Continuation Monad in its composition. Erik is in the hot seat this time and it's always a real pleasure to converse with Erik and Brian in the same room at the same whiteboard.

Now, what is Rx?

The .NET Reactive Framework (Rx) is the mathematical dual of LINQ to Objects. It consists of a pair of interfaces IObserver/IObservable that represent push-based, or observable, collections, plus a library of extension methods that implement the LINQ Standard Query Operators and other useful stream transformation functions.

interface IObservable<out T> 
{      
    IDisposable Subscribe(IObserver o);
}

interface IObserver<in T> 
{     
    void OnCompleted();     
    void OnNext(T v);      
    void OnError(Exception e); 


Observable collections capture the essence of the well-known subject/observer design pattern, and are tremendously useful for dealing with event-based and asynchronous programming, i.e. AJAX-style applications. For example, here is the prototypical Dictionary Suggest written using LINQ query comprehensions over observable collections:

IObservable<Html> q = from fragment in textBox

               from definitions in Dictionary.Lookup(fragment, 10).Until(textBox)

               select definitions.FormatAsHtml();

 

q.Subscribe(suggestions => { div.InnerHtml = suggestions; })



Please subscribe to this Channel 9 interview to be notified when we have clearance to distribute Rx over the counter (lame puns intended Smiley.

Tune in. This should prove to be an instant classic besides being a very important episode of E2E. Rx is deep, man. Deep.

Enjoy!

Tags:

Follow the Discussion

  • Oh my! Oh my! Smiley Too cool: Erik, Wes and Brian. More please. I've been wondering what Wes has been up to since his blog went dark.

  • Allan LindqvistaL_ Kinect ftw

    whoa eric brian and wes. talk about crssing the streams Smiley cant wait to watch this one

    (also hoping against hope for some natal somewhere in there Wink )

  • CharlesCharles Welcome Change

    Wes actually isn't in this one, but he is there, in spirit! Smiley You will see Wes soon on another edition of Going Deep. We have some ideas for an E2E with Wes as well. This one, however, is Brian and Erik (which is more than enough brain power, knowledge and passion to fill the room). From astrophysical examples to pseudo Haskell, this conversation has it all! Smiley

    I do want to point out (again) that Wes is a key contributor to Rx (which is why his blog has gone dark).

    Make the time to watch this. Yes, I know, it's long. If you have some spare time and really want to geek out for a solid hour, then do watch this and listen carefully. This is deep (in a profound way).

    C

  • Allan LindqvistaL_ Kinect ftw

    watching it now Smiley i saw erics talk about rx on lang.net (i think it was) and his coin example sounded hilarious Smiley to bad they didnt shoot him talking then because it seemd to be alot of visuals besides the slides. did he actually have a bunch of coins and threw them at people? Smiley

    totally off topic:

    if you hold shift while right clicking on a taskbar button in win7, you get the classic context menu with the move/maximize/minimize options. great if your media player is on your other monitor (the TV in my case) Smiley

  • Great video! Really fascinating. I can't wait to see the code - just push it to me Smiley

    A question: The scope of the  IDisposable object returned by Subscribe() was unclear to me. Erik implies you can put it in a using statement, like a normal IDisposable. But the lexical scope of the IDisposable returned seems much different than the lifetime ("runtime scope"?) of the IObserver you pass in. For example, the using statemetn with IDisposable for files is pretty obvious:

      using(fs = new Stream("somefile.txt"))   
      {     
        // ... do work on fs ...   
      } // fs is closed and disposed. 

    But in the IObserver case, I don't think the using statement's scope is appropriate for indicating you don't care about events anymore. Using the autocomplete example above:

    using(q.Subscribe(suggestions => ... ))
    {
    // ???
    }

    What happens in the body of the using statement? All the work seems to occur in the lambda passed to Subscribe. If I understood correctly, as soon as we leave the scope of the using statement, my lambda stops receiving events. Hmm, I bet the object implementing IDisposable has the secret sauce for the reactive framework. Maybe it has a method for testing for conditions and will "yield" until the condition is met? For example if I had another observer which looked for ENTER or TAB on the textbox and indicated that a selection was made, maybe it would let me write this code:

    class KeyObserver :  IObserver<...>
    {
    publi c bool SelectionMade()
    }

    KeyObserver key = ...;

    using(cntrl = q.Subscribe(suggestions => ... ))
    {
    if(! key.SelectionMade())
    sleep;
    }
    // selection has been made and we stop listening to suggest events

    Hopefully that makes some sense. It looks like the beginnings of a way to do reasonable event based programming. Apologies for answering my own question but glad to hear if I'm on track ...

    Two other notes:

     

    Great stuff, get me this code! Smiley

    Justin

  • Excellent observation. If you ever get a chance to see my "fundamentalist functional programming" talk, you will see that combining side-effect, closures + using- and try-catch-blocks is my favorite source of fun "what does this code do?" puzzles.

    For instance, your own example of using "using" for files is not really that "obvious". What if inside the block you capture fs in a closure, or in general stick it in the heap somewhere? I have seen examples like this

      IEnumerable<string> lines;
      using(fs = new Stream("..."))
      {
        lines = from l in fs.ReadLines() where l.Length > 256 select l;
      }

      foreach(var l in lines)
      {
        // oops, fs has been disposed before the query has been executed
      }

    Brian asked the question "can you put it in a using statement", to which the only correct answer is "yes". Had he asked "is that a smart thing to do?" I would have said that the using statement can be very powerful, but as always with great power comes potential danger.

  • CharlesCharles Welcome Change

    Niner head.in.the.box = Erik Meijer. Just so you know. Wink

    C

  • Be sure to check out Eric's talk at Lang.NET Symposium 2009 (which he alluded to in this video) and Anders Hejlberg's covariance/contravariance in C# 4.0 talk.

    Using disposable resources like FileStreams in the deferred execution model of LINQ queries (and closures in general) can be frustrating.  Beware of leaks as well as premature disposals.

  • William Staceystaceyw Before C# there was darkness...

    Love it guys.

    While watching I was thinking about the analogy between IObservable<T> and the CCR's Port<T> and how it sounds like a port abstraction.  Port<T> allows you to monitor a port with various typed-listeners and you can listen for stop, exception, and value results (and also return result back to the port) and also do things like Choice over various ports.  How does IObservable compare/contrast to the port model? 

    How does fifoness play into this?  I know with Port, sometimes you have to manually assure fifoness because of the inherent concurrency.

    btw - "Please subscribe to this Channel 9 interview..".  You guys jest, but that could be a killer feature.  Being able to post arbitrary Observer code in a c9 reply that could do work for you (i.e. send a tweet, send a mail, etc) based on some code in your observer.  Like a little bot script.  That could be the next big thing in blogs and forums.  High geekness factor.

  • Allan LindqvistaL_ Kinect ftw

    heavy stuff Smiley

    im most likely missing something but isnt this very similar to how events work? the event is sort of like the Ioberservable and the delegate you "pass in" with += is like the Iobserver? also, in the code example above you call a method called subscribe, why is that? is that equivalent to the implicit "subscribe" of th e += syntax? in the discussion of event its mentioned that you can sort of leak delegates to the event, but isnt that also true for Iobserveble?

    Rx seems very cool but i still feel i havent completly wrapped my brain around it Smiley cant wait for more info on this Smiley

    --edit--

    aah, is the "linq" statement above just in essennce just defining whats beeing oberved? so the Iobserver not only knows its observing "something" it also encapsulates what exactly it observes,  in this case the "fragment" in "textbox"

    i feel im getting a little closer to understanding this, but i cant wait for some code/examples Smiley

    --edit2 post rewatch--

    hm my original questions seems somewhat trivial, of course it similar to events, but Rx is event on sharksteroids Smiley this is what i consider trlu beautiful code, its sooo simple but incredibly powerful.. just like ienumerable Smiley

  • Adam SpeightAdam​Speight2008 The Bandito Coder

    To see if I have grasped the basic concepts, i summarised them. Are they correct?

    IEnumeratable & IEnumerater: Over there is some stuff, take something from it and put it over there.

    IObservable & IObserver: When you have something don't pass it to me, place over there.

  • Truly fantastic.. Please make it MS-PL so it's available on Mono..

    Thanks..

     

  • ChadkChadk excuse me - do you has a flavor?

    This is flippin' cool!

  • Brent LambornBrentL Brent

    My brain just got kicked right in the ambient monads.

  • Yup, sounds like you got it. Since I love sushi, the analogy I like to use is

    IEnumerable/IEnumerator: sit at the sushi bar and ask the chef for each next piece.
    IObservable/IObserver: sit at the conveyer belt and pick the next piece that is psuhed at you without being asked.

  • CharlesCharles Welcome Change

    Excellent analogy. Makes me want sushi in addition to better understanding what you and Wes have come up with. Thanks!
    C

  • Exactly right. It captures the essence of what an "event stream" or "asynchrnous computation" is and makes it into a first class concept.

  • Awesome!  Of course no where near the "polishness" or completeness of your work but recentley I implemented a class to follow up the progress of worker threads that fits perfectly pattern of the IObserver interface. 

    It's nice to see how my device is validated by your work or that I can now say I've used things with fancy names: "hey! I've used reacting programing"Cool

  • Bent Rasmussenexoteric stuck in a loop, for a while

    As usual this is looking terrific (and watching the preview at lang.net this is looking promising... back to watching)
    One more thing: using Maybe<T>, you could replace MoveNext: () -> Bool with MoveNext: () -> (); of course the whole thing could be implemented as just Next: () -> Maybe<T> to begin with. That would break command/query separation in a way, so maybe Next: () -> () and Item: () -> Maybe<T> is better.

  • Bent Rasmussenexoteric stuck in a loop, for a while

    [Functional] Reactive Programming (FRP). Now Object-Oriented Reactive Programming (OORP)?

  • Bent Rasmussenexoteric stuck in a loop, for a while

    In the C# world we have exceptions, so in the context of C# it is appropriate to model errors directly in the IObserver interface right, although one could do away with exceptions as side-effects and model them as types - which would probably be a more disruptive programming model. Hmm...

  • You can turn an IEumerable into an IObservable by doing something like this:

     

    while(it = MoveNext()) callback.call(it)

    Or you can sample every second, or sample when something else happens, etc.

    Can you do the reverse with Rx: turn an IObservable into an IEnumerable? If you have coroutines you can do that by setting up a coroutine that subscribes to the IObservable and every time it gets called it yields the element it receives. I've seen this trick used somewhere to turn an collection interface that has only ForEach into a IEnumerable with MoveNext.

    Edit: You could also use a thread of course but that would be very expensive.

    An intuitive explanation goes like this.

    You have a Supply and a Demand. Your job is to get stuff from the Supply to Demand. Now, there are two types of Supplies:

    1) PushSupply, they push stuff to you (IObservable)

    2) PullSupply, you have to ask them (IEnumerable)

    Likewise, there are two types of Demand:

    1) PushDemand, you push stuff to the Demand whether they like it or not (user of IObservable)

    2) PullDemand, they pull stuff from you (user of IEnumerable, they pull with MoveNext & Current)

    If you have a PushSupply and a PushDemand you can just hook them up. They work together naturally. If you have a PullSupply and a PullDemand you can also just hook them up.

    A small problem arises if you have a PullSupply and a PushDemand. Now you have to pull stuff from the Supply personally and push it to the Demand. You can do this by pulling and pushing as fast as you can:

    while(MoveNext()) callback.Call(Current)

    Or you can sample every second, for example.

    A bigger problem is bridging the gap between a PushSupply and a PullDemand. The PushSupply pushes stuff in your hands but what can you do if the PullDemand doesn't want it yet? And what do you do if the PullDemand wants new stuff but the PushSupply hash't pushed anything?

    One way to do that is this: if the PushSupply wants to give you something but the PullDemand doesn't need it yet, you stop the supply and wait until the demand wants it. If the demand wants something but the supply hasn't pushed yet you stop the demand and wait until the supply gives you an item.

    You could also put stuff in a buffer. It depends on the situation: if you have a collection like thing with only a ForEach method you wouldn't want to put the entire collection in the buffer. Especially not with an infinite collection, because you don't have an infinite buffer! You want to execute the producer and consumer in lockstep. Or if they run concurrently with a bounded buffer. Does Rx support these things?

    Very interesting video!

  • Allan LindqvistaL_ Kinect ftw

    right, and they're also composable, unlike events!

    chaining/joining events together is kind of painful but its easy with IObservers. and then there is filtering and all that. Also, it seems like IObservers would be great for Ansyc scenarios. i belive someone mentioned that in the comments too Smiley are you doing anything perticular with the TPL team or with the CCR?

    you could stretch the sushi analogy even further, events are like the sushi chef making diffrent sushi pieces and handing them to you leaving you to pick out the ones you like. But IObserver is like a waiter into whom you encode what pieces you like and he'll only bring you those. the chef doesnt have to keep track of what you want, he only makes random sushi and you dont have to filter the sushi as its coming in, you tell the waitor once and the stream of sushi comming at you is already filterd. it also works for joining, you tell the waitor that you only want to have your calefornia roll with a salmon piece, and the waitor can bring you those in pairs even if there are two chefs working asynchronosly and you dont have to do any joining in you handler code. (ie, putting the calefornia roll in your mouth and then sitting there, mouth open waiting for the salmon, that'd look silly, and its silly to do it in code too)

    is that correct? Smiley

     

    --edited post, added sushi--

  • Edmondo Pentangeloepentangelo holoed

    Very beautiful and simple.

    I was so impressed by the simplicity of it all that I tried to do a sample implementation in C#.
    Did I get it right?

    http://reactivelinq.codeplex.com

  • This is really great, especially the tie-in with concrete mathematical concepts.  It does, however, make me wonder if this pattern could be expanded upon to handle a "distributed" observer pattern, where remote clients (identified by a URI, not a function pointer) can subscribe to events occurring another machine.  I've worked on projects doing just this in the past (via SOAP/HTTP), but it's a lot of plumbing.  WCF does support the notion of callbacks, but to say their approach is intuitive is a bit of a misnomer (quite ugly if you ask me).

     

    Thoughts?

  • Pretty cool work. I think your implementation points out a few issues that this approach has to deal with.

     

    1) SpotAgent allows many subscribers; RiskAgent only one -- That says the Subscribe method isn't giving enough information (and the IObservable interface isn't rich enough). I wonder how you could indicate that a given Observable allows many observers vs. one?

     

    2) One problem that Erik points out with IEnumerable is the "subscriber" which calls GetNext() has no control over how long the "publisher" take to return the next value. I think IObservable reverses this problem. That is, the "publisher" (IObservable object) has no control over how long given "subscriber's" (IObserver) OnNext method will take to complete. You can see this issue in the Tick() methods for SpotAgent and RiskAgent.

     

    Does the composobility of IObservable/IObserve help solve this problem?

     

    Looking at your code definitely exposes some issues that I'm sure Erik's team has faced when developing their library.

  • Yup it does work. Our primary use-case for Rx is actually distributed programming (when doing tier-splitting).

  • 1) Your particular implementation of IObservable could take care of that. However, one vs many subscribers is an excellent example of a property that is not closed under composition. I can always compose your observer with another one that broadcasts its single subscription to multiple subsequent subscribers without the underlying source knowing about that. 

     

    2) The publisher could run all subscribers on a different thread, or even each call to the observer methods.

  • I didn't see any announcements about this, so forgive me if this is a repost, but has this accidentally (or perhaps intentionally?) shipped with the Silverlight Toolkit?

  • CharlesCharles Welcome Change

    Nope. This hasn't shipped yet. Smiley

     

    But it will.

    C

  • Edmondo Pentangeloepentangelo holoed

    Just for the fun of it,

    I've added an F# implementation of SelectMany and Select for IObservable in F#.

    http://reactivelinq.codeplex.com/

     

    holoed

    http://fsharpcode.blogspot.com/

  • Allan LindqvistaL_ Kinect ftw

    rx has apparently made it into the silverlight toolkit Smiley

    http://themechanicalbride.blogspot.com/2009/07/introducing-rx-linq-to-events.html

  • Edmondo Pentangeloepentangelo holoed

    Is RxLinq part of the Microsoft Tesla long term initiative ?

  • Once you tier-split a computation to run across tiers, you *must* solve the asynchronous programming problem. If you remember, our previous release used callbacks for asynchronous calls.

     

    Rx is the fruit of our efforts to come up with a general model of asynchronous computations that applies to a wide range of scenarios, including tier-splitting. 

     

    Wow, that sounds like a marketing pitch, but it is actually technically accurate.

  • Isn't that a nice surprise Smiley

  • Allan LindqvistaL_ Kinect ftw

    it was actually Smiley im having som compilation issues when using it with a regular .net project though, most likely because its a silverlight dll. also, i cant wait to hands on some docs, what is the Amb extension method for example? and does Rx use tpl for synchronization? 

    questions, questions.. Smiley

  • http://community.schemewiki.org/?amb

  • A little brainstorming after having watched the video:

     

    S1 ; S2

     

    In the language of event-driven/reactive paradigms this could be read as: statement 2 is one observer of the state manipulations done by statement 1... now guys hold on to your brains: what happens when there is more than one observer to S1? The whole idea of one statement after another "breaks" as S1 is followed by S2a and at the same time by S2b and S2c etc.etc. S2a, S2b S2c etc all get notfied and start executing at the same time... A program transforms from a list of statements into a tree of statements? Parallel computing? Speculative computing? Quantum computing?

     

    It is deeply (almost disturbing and) fascinating to see how IObserver actually covers the continuation monad, which more or less seams to be the essance of "statement after statement with shared state" programming. One statement tells the next to execute or communicating an error or the end of the program.

     

    Another twist: what happens when one statement S2 can get hold of the handle connecting/making it the succesor of S1 (the IDisposable obj) .... statements reconnecting? Programm-parts actively rewireing based on meta-state? 

     

    How about not using IDisposable but instead an extended "handle" allowing not only to stop the subsription but also to interrupt (for certain time?) or control it otherwise? (have to admit i did not check out the code yet, maybe that is already available)

     

    And the last for today: what other dualities are there waiting to be found? Wink

     

  • I would just like to ask, since Erik mentioned that this IObservable captures the essence of a Continuation, does that mean something like call-with-current-continuation could be implemented in C# using the IObservable?

     

    I am not very familliar with C#, and I have never fully grokked call/cc, so bear with me if this question is lacking some basic fundamental understandings of either!

  • If you're interested in a nice challenge with Rx, go over to my blog and try solving the tripple-click puzzle: 

     

     

    http://blogs.msdn.com/jeffva/archive/2009/08/11/fun-system-reactive-puzzle.aspx

     

  • Did you forget something?

     

    The Subsrciber to the Observer assumes that the Observer, and the connection to the Observer, are functional during the life of the subscription. If the Observer, or the connection to the Observer, fail, the Subscriber may never know and assume that all is well when it is not. What happens to the Subscriber if the Observer, or the interface to the Observer, fail? How is that handled?

     

    Are other features required so that the Subscriber can periodically verify the health of the Observer and not blindly assume that everything is OK when no events are received ?

  • slasla

    Awesome!

    Can we please have more of Erik with Brian together.

    Let them discuss varinats in type system or other academic stuff. Or mroe real life MSR projets, for example spec#, spec explorer, axum etc.

    Maybe someday you can get Yury Gurevich and Tony Hoare together Smiley

     

     

    Thanks Charles, awesome video.

     

  • CharlesCharles Welcome Change

    Absolutely. And I've been meaning to vist Yuri again. Yuri has many great things to say. He's brilliant. Erik, Brian and Yuri. Yes, I LOVE the sound of that.

     

    We're very lucky that Brian and Erik are both HUGE fans of Channel 9 and the Niner nation! Smiley

     

    C

  • Wow. Were they way off on the covariance and contravariance example earlier in the video. Btw, the array covariance in c# is broken, and it was never legal (or wise) to have a Apple[] have a Fruit[] as the backing storage. Erik was plain wrong on that being safe. Anyhow, a cool vid otherwise.

  • DouglasHDouglasH Just Causual

    I think they were implying the work done around co and contravariance in C# 4.0.  Could be wrong though.

     

    Douglas

  • CharlesCharles Welcome Change

    Indeed. They were addressing the new additions to C#...

    C

  • I was also unhappy about the covariance / contravariance discussion, so I'd like to work something up for ch9 for the near future.

     

    I did peek at my old physics notes, and here's the gist from physics. Consider a parametric curve, meaning a function p(t) from a real-valued parameter, call it t, to abstract geometric points p in some space M. In calculus on manifolds, we learn that such points have various coordinate systems -- functions from abstract points p to n-vectors of real numbers (x1(p), x2(p), ..., xn(p)), such that we have differentiable functions from each coordinate system to all the others around every point. That means we can always identify abstract points p with n-vectors of real numbers, (x1(p), x2(p), ..., xn(p)) -- the coordinates of the point, in various ways -- say another set is (y1(p), y2(p), ..., yn(p)), so that the derivatives dxi/dyj and dyj/dxi exist (where i and j vary from 1 to n, inclusive).

     

    Now consider a function f(p) from the points p on the manifold to something else (usually some other real vectors but it doesn't matter). What happens with df(g(t))/dt when we change coordinate systems? By the chain rule, df/dt = sum(i=1..n, (df/dxi)*(dxi/dt)). But

     

    1) df/dxi = sum(k=1..n, (df/dyk)*(dyk/dxi)) -- a.k.a. covariant co-vector

    2) dxi/dt = sum(l=1..n, (dxi/dyl)*(dyl/dt)) -- a.k.a. contravariant vector

     

    Quantities that vary in the same way as df/dxi are called co-vectors and are covariant. Here's a mnemonic. Abbreviate df/dxi as f,xi and automatically sum over repeated indices. Rewrite equation 1 as

     

    f,xi = f,yk * dyk/dxi.  See the y's "upstairs" in the dyk/dxi on the right-hand-side?  UPstairs means COvariant. Now look at equation 2 -- abbreviate dxi/dt as x.i :

     

    x.i = y.l * dxi/dyl. See the y's "downstairs" in the dxi/dyl on the right-hand-side? DOWNstairs means CONTRAvariant. Such things are called vectors.

     

    Ok, now how we turn these relationships amongst Coordinate Transformations into relationships amongst Types and Subtypes would be the questions I would ask to draw an analogy between co/contra variance in physics and co/contra variance in programming languages.

     

    Ideas anyone? Can we relate types and subtypes to differentiable coordinate transformations? Is the "type" of an object similar to the "coordinates of a point?" Can the derivatives of the coordinate transformations (dxi/dyk) somehow be related to type coercions?

  • For what it's worth, a solution to the deferred disposal problem can be found here: Using IDisposables with LINQ. The filestream example would look like this:

    IEnumerable<string> lines =
        from fs in new Stream("...").Use()
        from l in fs.ReadLines()
        where l.Length > 256
        select l;
    foreach(var l in lines)
    {
        // fs will be disposed with the enumerator
    }

    The same approach can be used with a delegate to defer creation as well as disposal: () => new Stream("..."). A use keyword, a la F#, would be even better.

  • Bent Rasmussenexoteric stuck in a loop, for a while

    I was quite happy with the coverage - it was already unusual to mix physics and programming this way - very stimulating although beyond me. One of the best parts was the formulation of co- and contravariance rules via sequent notation, dualization and showing a statement sequence as a series of continuations, if I got that right. Definitely a video that expands horizons. And this stuff about ambient monads. I'm not sure that was really covered anywhere, was it?

  • I'm wondering if given the excitement about the dual nature, we might be losing part of the intention of IObservable.

     

    First of all, I'm thinking there might be a bit of a mismatch in the duality anyway.  Primarily, IEnumerator and IEnumerable have a many-to-one relationship, whereas IObserver and IObservable havea many-to-many relationship, right?  The deal is that IEnumerator has to have intimate knowledge about the structure of its IEnumerable that the app doesn't necessarily have; they're tightly bound.  Whereas IObserver and IObservable are completely unaware of each others' internals. 

     

    I think the dual of IEnumerable would be something more like ILoadable, where you call ILoadable.GetLoader(), which then allows you to load values into an "array" or whatever, using Loader.MoveNext(bool) and Loader.SetValue(T).  I certainly think the intention of IObservable is more valuable than any ILoadable concept (though ILoadable might be an interesting way to explore inserts and updates), so I wonder if the focus on duality is perhaps the wrong way to go about it.

     

    For example, I'm not sure I get the point of the OnError method.  First of all, isn't there a duality mismatch here anyway—given that IObserver.OnNext(T) could also throw an exception, then to preserve absolute duality going the opposite direction, shouldn't we require that OnError also be a part of IEnumerator?  But beyond that, it just doesn't seem to fit.  Why would the Observable need to tell all Observers that there was some exception downstream?  Just like an iterator doesn't need to know that there's an exception occurring in the app that uses it.  So I think the focus on preserving duality really mucks up the intention of IObservable in this case.

     

    Also, I think if duality was that important to the concept of IObservable and IEnumerable, then the dual of (for example) IList would be even more powerful.  But wouldn't the dual of (for example) IList.Set(int, T) be IListDual.Get(out int, out T)?  Is that useful in some fashion?  I don't see anything, though I'd love to hear from anyone with an idea how it could be powerful.

  • Covariant/contravariant! 

     

    Help! Someone call Eric Lippert Smiley

  • Apple[] as
    Fruit[] fs = as
    Fruit f = fs[0]
    fs[1] = new Banana

     

    In C#, the last line will throw ArrayTypeMismatchException. : Angel

  • Hi Guys,

    Can someone explain this:

    var values = (new[] { "test 1", "test 2", "test 3" }).ToObservable();

    values.ToEnumerable().AsParallel().ForAll(Console.WriteLine);

    ForAll method will never return. Why is this happening (I have November rx release for .net 3.5)?

    Thank you.

  • I'd be curious to know any of your thoughts on my own implementation of IObservable, which I had to rename to INotify since Microsoft is rolling the Reactive Framework out and including it in .NET version 4. I too was frustrated with managing weak event references as well as the implementation of events in WPF and now Silverlight using INotifyPropertyChanged versus DependencyProperty. Let me know if I have a screw loose or if I'm on the right path...

  • Brandon M. HunterBMH

    What is the difference between a publish/subscribe and observer/subject architectures?

  • What Rx does is Angel provide an interface for the subject/observer pattern in the form of push-based collections, and (b) show that these interfaces form a Monad, and hence you can compose transformations on push-based collections using the LINQ standard query operators, and (c) prove that the subject/observer pattern is dual to the iterator pattern.

  • Just started watching this. About co/contravariance w.r.t. subtyping: producer types are covariant, and consumer types are contravariant to subtyping. Apple is a subtype of Fruit: wherever Fruit is used, Apple can be used too: A <: F. That is because any quality Fruit has, Apple has too.

     

    Array read is a producer: give it an Int and it gives you an Apple. Now, A <: F => (Int->A) <: (Int->F). Wherever we use (Int->F), it gives us Fruits, so we must be prepared to handle Fruits there. But it's OK to use (Int->A) instead 'coz it'll give us Apples, which can go instead of Fruits always.

     

    With consumers it's the other way around. A<:F => (F->Int) <: (A->Int). Wherever we use Apples consumer, (A->Int), it is prepared to use Apples. So it means we must be supplying it with Apples. So we can use fruits consumer (F->Int) in its place, because this fruits consumer can always use Apples instead of Fruits.

     

    Graphically, we can envision the producers/consumers as pipes with a certain diameter - small for apples, bigger for fruits. There are many more fruits than there are apples - bananas too etc. Now, for a wide inlet of fruits consumer (us, in the 1st case), it can just as well handle all input from a narrower outlet of an apples producer. In the 2nd case, the narrow outlet of apples producer (us) can just as well go into a wider inlet of fruits consumer in general.

     

    Array read is a producer; array write is a consumer. Does this make sense?

     

    EDIT: and in general, covariant, when translated from Latin I gess, just means "changing with the direction of change", and contravariant means "changing in the opposite direction of change". Say we do something that enlarges one thing, and another one grows too, than it is covariant to the first w.r.t. our action. If it consistently shrinks, we say it's contravariant to the first w.r.t. our action.

     

    For example, imagine you travel from city A to city B in one straight line. The further you go along the route, the further you are from the city A, so your distance from city A is covariant with the distance you travel in the car. But the distance to city B is contravariant to it - it grows smaller as you travel. I guess a "travel operator" in its covariant form will reflect the enlargement of the distance as measured from the origin point. But in its contravariant form it will show the shrinkage of distance as measured to the destination.

     

    Or take rotation: say we have a point on a plane, in some coordinate system. Now let's apply rotation to that plane. Point's coordinates will change WITH the plane's rotation, or covariantly. But what if we apply rotation to the coordinate system instead? Now the point's coordinates will change _in the opposite direction_ to the rotation, or contravariantly. That's where these terms come into physics from.

Remove this comment

Remove this thread

close

Comments Closed

Comments have been closed since this content was published more than 30 days ago, but if you'd like to continue the conversation, please create a new thread in our Forums,
or Contact Us and let us know.