Comments (1)
The simplest way to look at this might be to consider plain Rx—the IObservable<T>
and IObserver<T>
interfaces built into the .NET runtime libraries. Those were the original incarnation of the push dual of IEnumerable<T>
/IEnumerator<T>
.
Calling Subscribe
on an IObservable<T>
means you want to start receiving items from it, so its counterpart is calling GetEnumerator
on an IEnumerable<T>
.
Calling Dispose
on the IDisposable
returned by IObservable<T>
indicates that you don't want to continue to receive items from the source, regardless of whether the source has more to give. In the pull world, we indicate this by calling Dispose
on the IEnumerable<T>
.
So there's a sense in which the IEnumerator<T>
is the equivalent of the object returned from Subscribe
: each individual consumer of events gets one of these; if multiple consumers are retrieving items from a source concurrently (where supported) each will have its own IEnumerator<T>
in the pull world, and each will have its own object returned from Subscribe
in the push world.
So then moving back to the Reaqtive world, with its augmented concept of subscription, the subscription object returned by IObservable<T>.Subscribe
corresponds to the IEnumerator<T>
.
This might sound surprising because people often talk about the IObserver<T>
being equivalent to the IEnumerator<T>
. It is, and it isn't. There's a catch here: when we flip the arrows, one of them doesn't get flipped:
Operation | Initiator with IEnumerable | Initiator with IObservable |
---|---|---|
Receive next item/error/end | Consumer | Source |
Terminate before reaching end | Consumer | Consumer |
So when going from pull to push, we go from the consumer fetching items to the source pushing items. But when it comes to deciding to stop early, that's a consumer-driven decision in both worlds. Even in Rx's push-based world, it's still the consumer of events that gets to decide that they want to stop early.
This leads to an asymmetry in the design. In the pull world, both the receive next and the terminate operations are initiated by the consumer invoking a method on the IEnumerator<T>
(MoveNext
and Dispose
respectively). But in the pull world, receive next involves the source calling a method on the consumer, but terminate involves the consumer calling a method on the source.
So in the pull world, there needs to be a bidirectional association between source and consumer. The source needs to be able to invoke the consumer's OnNext
, OnCompleted
and OnError
, so the consumer must supply an IObserver<T>
, but the consumer needs to be able to call Dispose
on the source to terminate early, which is why IObservable<T>.Subscribe
returns an object. You have what is conceptually a single thing—a subscription—but it is manifest as a connected pair of objects (the IObserver<T>
and the subscription) because of the need for bidirectional communication.
The equivalent concept in IEnumerable<T>
doesn't need a pair of objects because all the method invocations go in one direction: from consumer to source. The consumer doesn't need to supply an object to the source because the source never calls methods on the consumer. So instead of the pair of objects—IObserver<T>
and subscription—the pull world represents the same concept with just one object, IEnumerator<T>
.
But what about traversal of the computation graph? Well that's the main reason I said to look at the original Rx version: subscriptions in that world didn't provide such a service, which was exactly consistent with the fact that enumerables don't offer a way to do that either. Reaqtive makes subscriptions slightly more powerful, with this ability to walk the computation graph. But there is no equivalent of this in the pull world. You could imagine some augmented alternative to IEnumerator<T>
that did offer such a thing, as the dual of this Reaqtive feature. But Reaqtive doesn't define any such thing for the pull world in practice.
from reaqtor.
Related Issues (20)
- Docs: need actually explain what this framework is, why you should use it, and how it works HOT 8
- Can Reaqtor be used to create a native LINQ DBMS? HOT 2
- [Proposal] Operator: Chunk HOT 1
- Visual Studio 2019 first time solution build fails HOT 3
- ExpressionEqualityComparator generates different hash code for equal expressions containing LabelTarget
- Shebang Generated.tt failing to reference Reaqtive assemblies HOT 2
- Code analyzer errors when building with .NET 7.0 SDK
- Nuget build of latest beta version HOT 3
- StringSegment test fails due to .NET 6.0 fixing a bug in string.Remove HOT 2
- Approaches for state migration with Reaqtive HOT 1
- Moving to the new .NET Foundation CLA service HOT 1
- Bonsai.Serialization notebook getting started broken HOT 3
- Work around roslyn 41640
- Nuqleon.Linq.Expressions.Optimizers causes IDE0001 diagnostic to run incredibly slowly HOT 14
- Question: Demo code for Reaqtor HOT 1
- Align with .NET 8.0 SDK analyzers
- Operator: Then
- Operator: When
- Operator: While
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from reaqtor.