I'm experimenting with Reactive Extensions on various platforms, and one thing that annoys me a bit are the glitches.
Even though for UI code these glitches might not be that problematic, and usually one can find an operator that works around them, I still find debugging code more difficult in the presence of glitches: the intermediate results are not important to debug, but my mind does not know when a result is intermediate or "final".
Having worked a bit with pure functional FRP in Haskell and synchronous data-flow systems, it also 'feels' wrong, but that is of course subjective.
But when hooking RX to non-UI actuators (like motors or switches), I think glitches are more problematic. How would one make sure that only the correct value is send to the external actuators?
Maybe this can be solved by some 'dispatcher' that knows when some 'external sensor' fired the initiating event, so that all internal events are handled before forwarding the final result(s) to the actuators. Something like described in the flapjax paper.
The question(s) I hope to get answers for are:
Is there something in RX that makes fixing glitches for synchronous notifications impossible?
If not, does a (preferably production quality) library or approach exists for RX that fixes synchronous glitches? Especially for the single-threaded Javascript this might make sense?
If no general solution exists, how would RX be used to control external sensors/actuators without glitches at the actuators?
Let me give an example
Suppose I want to print a sequence of tuples (a,b) where the contract is
a=n b=10 * floor(n/10)
n is a natural number stream = 0,1,2....
So I expect the following sequence
(a=0, b=0)
(a=1, b=0)
(a=2, b=0)
...
(a=9, b=0)
(a=10, b=10)
(a=11, b=10)
...
In RX, to make things more interesting, I will use filter for computing the b stream
var n = Observable
.Interval(TimeSpan.FromSeconds(1))
.Publish()
.RefCount();
var a = n.Select(t => "a=" + t);
var b = n.Where(t => t % 10 == 0)
.Select(t => "b=" + t);
var ab = a.CombineLatest(b, Tuple.Create);
ab.Subscribe(Console.WriteLine);
This gives what I believed to be a glitch (temporary violation of the invariant/contract):
(a=0, b=0)
(a=1, b=0)
(a=2, b=0)
...
(a=10, b=0) <-- glitch?
(a=10, b=10)
(a=11, b=10)
I realize that this is the correct behavior of CombineLatest, but I also thought this was called a glitch because in a real pure FRP system, you do not get these intermediate-invariant-violating results.
Note that in this example, I would not be able to use Zip, and also WithLatestFrom would give an incorrect result.
Of course I could just simplify this example into one monadic computation, never multi-casting the n stream occurrences (this would mean not being able to filter but just map), but that's not the point: IMO in RX you always get a 'glitch' whenever you split and rejoin an observable stream:
s
/ \
a b
\ /
t
For example, in FlapJAX you don't get these problems.
Does any of this make sense?
Thanks a lot,
Peter
Update: Let me try to answer my own question in an RX context.
First of all, it seems my understanding of what a "glitch" is, was wrong. From a pure FRP standpoint, what looked like glitches in RX to me, seems actually correct behavior in RX.
So I guess that in RX we need to be explicit about the "time" at which we expect to actuate values combined from sensors.
In my own example, the actuator is the console, and the sensor the interval n.
So if I change my code
ab.Subscribe(Console.WriteLine);
into
ab.Sample(n).Subscribe(Console.WriteLine);
then only the "correct" values are printed.
This does mean that when we get an observable sequence that combines values from sensors, that we must know all the original sensors, merge them all, and sample the values with that merged signal before sending any values to actuators...
So an alternative approach would be to "lift" IObservable into a "Sensed" structure that remembers and merges the originating sensors, for example like this:
public struct Sensed<T>
{
public IObservable<T> Values;
public IObservable<Unit> Sensors;
public Sensed(IObservable<T> values, IObservable<Unit> sensors)
{
Values = values;
Sensors = sensors;
}
public IObservable<Unit> MergeSensors(IObservable<Unit> sensors)
{
return sensors == Sensors ? Sensors : Sensors.Merge(sensors);
}
public IObservable<T> MergeValues(IObservable<T> values)
{
return values == Values ? Values : Values.Merge(values);
}
}
And then we must transfer all RX method to this "Sensed" structure:
public static class Sensed
{
public static Sensed<T> Sensor<T>(this IObservable<T> source)
{
var hotSource = source.Publish().RefCount();
return new Sensed<T>(hotSource, hotSource.Select(_ => Unit.Default));
}
public static Sensed<long> Interval(TimeSpan period)
{
return Observable.Interval(period).Sensor();
}
public static Sensed<TOut> Lift<TIn, TOut>(this Sensed<TIn> source, Func<IObservable<TIn>, IObservable<TOut>> lifter)
{
return new Sensed<TOut>(lifter(source.Values), source.Sensors);
}
public static Sensed<TOut> Select<TIn, TOut>(this Sensed<TIn> source, Func<TIn, TOut> func)
{
return source.Lift(values => values.Select(func));
}
public static Sensed<T> Where<T>(this Sensed<T> source, Func<T, bool> func)
{
return source.Lift(values => values.Where(func));
}
public static Sensed<T> Merge<T>(this Sensed<T> source1, Sensed<T> source2)
{
return new Sensed<T>(source1.MergeValues(source2.Values), source1.MergeSensors(source2.Sensors));
}
public static Sensed<TOut> CombineLatest<TIn1, TIn2, TOut>(this Sensed<TIn1> source1, Sensed<TIn2> source2, Func<TIn1, TIn2, TOut> func)
{
return new Sensed<TOut>(source1.Values.CombineLatest(source2.Values, func), source1.MergeSensors(source2.Sensors));
}
public static IDisposable Actuate<T>(this Sensed<T> source, Action<T> next)
{
return source.Values.Sample(source.Sensors).Subscribe(next);
}
}
My example then becomes:
var n = Sensed.Interval(TimeSpan.FromMilliseconds(100));
var a = n.Select(t => "a=" + t);
var b = n.Where(t => t % 10 == 0).Select(t => "b=" + t);
var ab = a.CombineLatest(b, Tuple.Create);
ab.Actuate(Console.WriteLine);
And again only the "desired" values are passed to the actuator, but with this design, the originating sensors are remember in the Sensed structure.
I'm not sure if any of this makes "sense" (pun intended), maybe I should just let go of my desire for pure FRP, and live with it. After all, time is relative ;-)
Peter
Related
As the name suggests I was wondering if it makes sense to use Protobuf without the requirement of having to serialize the data in any form at the moment (might change in future). I mean to use them purely as data structures to pass Information from one function to the other, all executed in the same address space. Or do you feel it may be an Overkill and see other alternatives.
Backgroud:
I have to design a lib that implements certain interfaces. At the moment, my collegues have implemented it using several functions taking arguments ..
Example:
void readA(int iIP1, int iIP2, Result& oOP)
void readB(std::string iIP1, Result& oOP)
void readC(std::vector<int> iIP1, Result& oOP)
I want to change this and provide just one interface function:
void ReadFn(ReadMsg& ip, ReadResult& res);
And the data structures are defined in Protobuf as below ..
message ReadMsg {
enum ReadWhat {
A = 0;
B = 1;
C = 2;
}
message readA {
int32 iIP1 = 1;
int32 iIP2 = 2;
}
message readB {
string IP1 = 1;
}
message readC {
repeated int IP1 = 1;
}
oneof actRead {
readA rA = 1;
readB rB = 2;
readC rC = 3;
}
}
It offers many advantages over traditional interface design(using functions), with very Little effort from my side. And it will be future proof should these components be deployed as Services in different processes/machines (ofcourse with additional implementation). But given that Protocol Buffers strength is their serialization Features, which I do not make use of at the moment, would you choose to use them in such trivial Tasks ?
Thank you
It can make sense to group function arguments into a struct if there are many of them. And it can make sense to combine your readA, readB and readC functions into a single function if they share a lot of common parts.
What doesn't, however, make sense in my opinion is introducing a separate .proto file and a protobuf dependency if you are not going to use it for serialization. Similar features for grouping data into reusable structures already exist in most languages. And when you use the built-in features of the language, all the code remains in the same place and is easier to understand.
quick question about an operator I've written for myself.
Please excuse my poor-man's marble diagrams:
zip
aa--bb--cc--dd--ee--ff--------gg
--11----22--33--------44--55----
================================
--a1----b2--c3--------d4--e5----
combineLatest
aa--bb--cc--dd--ee--ff--------gg
--11----22--33--------44--55----
================================
--a1b1--c2--d3--e3--f3f4--f5--g5
zipLatest
aa--bb--cc--dd--ee--ff--------gg
--11----22--33--------44--55----
================================
--a1----c2--d3--------f4------g5
zipLatest (the one I wrote) fires at almost the same times as zip, but without the queueing zip includes.
I've already implemented it, I'm just wondering if this already exists.
I know I wrote a similar method in the past, to discover by random chance that I'd written the sample operator without knowing it.
So, does this already exist in the framework, or exist as a trivial composition of elements I haven't thought of?
Note: I don't want to rely on equality of my inputs to deduplicate (a la distinctUntilChanged).
It should work with a signal that only outputs "a" on an interval.
To give an update on the issue: There is still no operator for this requirement included in RxJS 6 and none seems to be planned for future releases. There are also no open pull requests that propose this operator.
As suggested here, a combination of combineLatest, first and repeat will produce the expected behaviour:
combineLatest(obs1, obs2).pipe(first()).pipe(repeat());
combineLatest will wait for the emission of both Observables - throwing away all emissions apart from the latest of each. first will complete the Observable after the emission and repeat resubscribes on combineLatest, causing it to wait again for the latest values of both observables.
The resubscription behaviour of repeat is not fully documented, but can be found in the GitHub source:
source.subscribe(this._unsubscribeAndRecycle());
Though you specifically mentions not to use DistinctUntilChanged, you can use it with a counter to distinct new values:
public static IObservable<(T, TSecond)> ZipLatest<T, TSecond>(this IObservable<T> source, IObservable<TSecond> second)
{
return source.Select((value, id) => (value, id))
.CombineLatest(second.Select((value, id) => (value, id)), ValueTuple.Create)
.DistinctUntilChanged(x => (x.Item1.id, x.Item2.id), new AnyEqualityComparer<int, int>())
.Select(x => (x.Item1.value, x.Item2.value));
}
public class AnyEqualityComparer<T1, T2> : IEqualityComparer<(T1 a, T2 b)>
{
public bool Equals((T1 a, T2 b) x, (T1 a, T2 b) y) => Equals(x.a, y.a) || Equals(x.b, y.b);
public int GetHashCode((T1 a, T2 b) obj) => throw new NotSupportedException();
}
Note that I've used Int32 here - because that's what Select() gives me - but it might be to small for some use cases. Int64 or Guid might be a better choice.
Say for example I have an enumerable
dim e = Enumerable.Range(0, 1024)
I'd like to be able to do
dim o = e.ToObservable(Timespan.FromSeconds(1))
So that the observable would generate values every second
until the enumerable is exhausted. I can't figure a simple way to
do this.
You can use Interval together with Zip to get the desired functionality:
var sequence = Observable.Interval(TimeSpan.FromSeconds(1))
.Zip(e.ToObservable(), (tick, index) => index)
I have also looked for the solution and after reading the intro to rx made my self one:
There is an Observable.Generate() overload which I have used to make my own ToObservable() extension method, taking TimeSpan as period:
public static class MyEx {
public static IObservable<T> ToObservable<T>(this IEnumerable<T> enumerable, TimeSpan period)
{
return Observable.Generate(
enumerable.GetEnumerator(),
x => x.MoveNext(),
x => x,
x => x.Current,
x => period);
}
public static IObservable<T> ToObservable<T>(this IEnumerable<T> enumerable, Func<T,TimeSpan> getPeriod)
{
return Observable.Generate(
enumerable.GetEnumerator(),
x => x.MoveNext(),
x => x,
x => x.Current,
x => getPeriod(x.Current));
}
}
Already tested in LINQPad. Only concerning about what happens with the enumerator instance after the resulting observable is e.g. disposed. Any corrections appreciated.
You'd need something to schedule notifying observers with each value taken from the Enumerable.
You can use the recursive Schedule overload on an Rx scheduler.
Public Shared Function Schedule ( _
scheduler As IScheduler, _
dueTime As TimeSpan, _
action As Action(Of Action(Of TimeSpan)) _
) As IDisposable
On each scheduled invocation, simply call enumerator.MoveNext(), and call OnNext(enumerator.Current), and finally OnCompleted when MoveNext() returns false. This is pretty much the bare-bones way of doing it.
An alternative was to express your requirement is to restate it as "for a sequence, have a minimum interval between each value".
See this answer. The test case resembles your original question.
You could always do this very simple approach:
dim e = Enumerable.Range(0, 1024)
dim o = e.ToObservable().Do(Sub (x) Thread.Sleep(1000))
When you subscribe to o the values take a second to be produced.
I can only assume that you are using Range to dumb down your question.
Do you want every value that the Enumerable pushes to be delayed by a second?
var e = Enumerable.Range(0, 10);
var o = Observable.Interval(TimeSpan.FromSeconds(1))
.Zip(e, (_,i)=>i);
Or do you want only the last value of the Enumerable at each second to be pushed. i.e. reading from Enumerable that is evaluating as you enumerate it (perhaps some IO). In which case CombineLatest is more useful than Zip.
Or perhaps you just want to get a value every second, in which case just use the Observable.Interval method
var o = Observable.Interval(TimeSpan.FromSeconds(1));
If you explain your problem space then the community will be able to better help you.
Lee
*Excuse the C# answer, but I dont know what the equivalent VB.NET code would be.
Is there a way to have an observable sequence to resume execution with the next element in the sequence if an error occurs?
From this post it looks like you need to specify a new observable sequence in Catch() to resume execution, but what if you needed to just continue processing with the next element in the sequence instead? Is there a way to achieve this?
UPDATE:
The scenario is as follows:
I have a bunch of elements that I need to process. The processing is made up of a bunch of steps. I have
decomposed the steps into tasks that I would like to compose.
I followed the guidelines for ToObservable() posted here
to convert by tasks to an observables for composition.
so basically I'm doing somethng like so -
foreach(element in collection)
{
var result = from aResult in DoAAsync(element).ToObservable()
from bResult in DoBAsync(aResult).ToObservable()
from cResult in DoCAsync(bResult).ToObservable()
select cResult;
result.subscribe( register on next and error handlers here)
}
or I could something like this:
var result =
from element in collection.ToObservable()
from aResult in DoAAsync(element).ToObservable()
from bResult in DoBAsync(aResult).ToObservable()
from cResult in DoCAsync(bResult).ToObservable()
select cResult;
What is the best way here to continue processing other elements even if let's say the processing of
one of the elements throws an exception. I would like to be able to log the error and move on ideally.
Both James & Richard made some good points, but I don't think they have given you the best method for solving your problem.
James suggested using .Catch(Observable.Never<Unit>()). He was wrong when he said that "will ... allow the stream to continue" because once you hit an exception the stream must end - that is what Richard pointed out when he mentioned the contract between observers and observables.
Also, using Never in this way will cause your observables to never complete.
The short answer is that .Catch(Observable.Empty<Unit>()) is the correct way to change a sequence from one that ends with an error to one that ends with completion.
You've hit on the right idea of using SelectMany to process each value of the source collection so that you can catch each exception, but you're left with a couple of issues.
You're using tasks (TPL) just to turn a function call into an observable. This forces your observable to use task pool threads which means that the SelectMany statement will likely produce values in a non-deterministic order.
Also you hide the actual calls to process your data making refactoring and maintenance harder.
I think you're better off creating an extension method that allows the exceptions to be skipped. Here it is:
public static IObservable<R> SelectAndSkipOnException<T, R>(
this IObservable<T> source, Func<T, R> selector)
{
return
source
.Select(t =>
Observable.Start(() => selector(t)).Catch(Observable.Empty<R>()))
.Merge();
}
With this method you can now simply do this:
var result =
collection.ToObservable()
.SelectAndSkipOnException(t =>
{
var a = DoA(t);
var b = DoB(a);
var c = DoC(b);
return c;
});
This code is much simpler, but it hides the exception(s). If you want to hang on to the exceptions while letting your sequence continue then you need to do some extra funkiness. Adding a couple of overloads to the Materialize extension method works to keep the errors.
public static IObservable<Notification<R>> Materialize<T, R>(
this IObservable<T> source, Func<T, R> selector)
{
return source.Select(t => Notification.CreateOnNext(t)).Materialize(selector);
}
public static IObservable<Notification<R>> Materialize<T, R>(
this IObservable<Notification<T>> source, Func<T, R> selector)
{
Func<Notification<T>, Notification<R>> f = nt =>
{
if (nt.Kind == NotificationKind.OnNext)
{
try
{
return Notification.CreateOnNext<R>(selector(nt.Value));
}
catch (Exception ex)
{
ex.Data["Value"] = nt.Value;
ex.Data["Selector"] = selector;
return Notification.CreateOnError<R>(ex);
}
}
else
{
if (nt.Kind == NotificationKind.OnError)
{
return Notification.CreateOnError<R>(nt.Exception);
}
else
{
return Notification.CreateOnCompleted<R>();
}
}
};
return source.Select(nt => f(nt));
}
These methods allow you to write this:
var result =
collection
.ToObservable()
.Materialize(t =>
{
var a = DoA(t);
var b = DoB(a);
var c = DoC(b);
return c;
})
.Do(nt =>
{
if (nt.Kind == NotificationKind.OnError)
{
/* Process the error in `nt.Exception` */
}
})
.Where(nt => nt.Kind != NotificationKind.OnError)
.Dematerialize();
You can even chain these Materialize methods and use ex.Data["Value"] & ex.Data["Selector"] to get the value and selector function that threw the error out.
I hope this helps.
The contract between IObservable and IObserver is OnNext*(OnCompelted|OnError)? which is upheld by all operators, even if not by the source.
Your only choice is to re-subscribe to the source using Retry, but if the source returns the IObservable instance for every description you won't see any new values.
Could you supply more information on your scenario? Maybe there is another way of looking at it.
Edit: Based on your updated feedback, it sounds like you just need Catch:
var result =
from element in collection.ToObservable()
from aResult in DoAAsync(element).ToObservable().Log().Catch(Observable.Empty<TA>())
from bResult in DoBAsync(aResult).ToObservable().Log().Catch(Observable.Empty<TB>())
from cResult in DoCAsync(bResult).ToObservable().Log().Catch(Observable.Empty<TC>())
select cResult;
This replaces an error with an Empty which would not trigger the next sequence (since it uses SelectMany under the hood.
I'm writing an iPhone App, and I'm finding that as I add features, predictably, the permutations of state increase dramatically.
I then find myself having to add code all over the place of the form:
If this and that and not the other then do x and y and set state z
Does anybody have suggestions for systematic approaches to deal with this?
Even though my app is iPhone, I think this applies to many GUI cases.
In general, a user interface application is always waiting for an event to happen. The event can be an action by the user (tap, shake iPhone, type letter on virtual keyboard), or by another process (network packet becomes available, battery runs out), or a time event (a timer expires). Whenever an event takes place ("if this"), you consult the current state of your application ("... and that and not the other") and then do something ("do x and y"), which most likely changes the application state ("set state z"). This is what you described in your question. And this is a general pattern.
There is no single systematic approach to make it right, but as you ask for suggestions of approaches, here some suggestions:
HINT 1: Use as few and little real data structures and variables to represent the internal state as possible, avoiding duplication of state by all means (until you run into performance issues). This makes the "do x and y and set state z" thing shorter, because the state gets set implicitly. Trivial example: instead of having (examples in C++)
if (namelen < 20) { name.append(c); namelen++; }
use
if (name.size() < 20) { name.append(c); }
The second example correctly avoids the replicated state variable 'namelen', making the action part shorter.
HINT 2: Whenever a compound condition (X and Y or Z) appears many times in your program, abstract it away into a procedure, so instead of
if ((x && y) || z) { ... }
write
bool my_condition() { return (x && y) || z; }
if (my_condition()) { ... }
HINT 3: If your user interface has a small number of clearly defined states, and the states affect how events are handled, you can represent the states as singleton instances of classes which inherit from an interface for handling those events. For example:
class UIState {
public:
virtual void HandleShake() = 0;
}
class MainScreen : public UIState {
public:
void HandleShake() { ... }
}
class HelpScreen : public UIState {
public:
void HandleShake() { ... }
}
Instantiate one instance of every derivate class and have then a pointer that points to the current state object:
UIState *current;
UIState *mainscreen = new MainScreen();
UIState *helpscreen = new HelpScreen();
current = mainscreen;
To handle shake then, call:
current->HandleShake();
To change UI state later:
current = helpscreen;
In this way, you can collect state-related procedures into classes, and encapsulate and abstract them away. Of course, you can add all kinds of interesting things into these state-specific (singleton) classes.
HINT 4: In general, if you have N boolean state variables and T different events that can be triggered, there are T * 2**N entries in the "matrix" of all possible events in all possible conditions. It requires your architectural view and domain expertise to correctly identify those dimensions and areas in the matrix which are most logical and natural to encapsulate into objects, and how. And that's what software engineering is about. But if you try to do your project without proper encapsulation and abstraction, you can't scale it far.