I have two observables in my view model, one which is an Observable for value changed by UI and another which represents Exception raised when the command fails.
I would like to create an observable which emits values from first Observable when the exception is raised. In short I would like to get following results
Marble Diagram
Value (Observable 1) -- 1 --- 2 -------- 3 ------ 4 ---------------- 5 -----------
Exception (Observable 2) ----------- e ------------------------- e ------------ e --
ExpectedResult ----------- 2 ------------------------- 4 ------------ 5 --
You're looking for Sample.
Value
.Sample(Exception)
.Subscribe(...);
This will get the latest value from Value every time Exception emits a signal.
Can't really improve the 'Sample' response, but in case you wanted to build it with some of the older/original/core functions, essentially, you just need to combine a 'CombineLatest', plus a DistinctUntilChanged() on the Exception stream.
var values = new Subject<int>();
var exception = new Subject<Exception>();
values.CombineLatest(exception, Tuple.Create)
.DistinctUntilChanged(t => t.Item2)
.Select(t => t.Item1)
.Dump();
values.OnNext(1);
values.OnNext(2);
exception.OnNext(new Exception());
values.OnNext(3);
values.OnNext(4);
exception.OnNext(new Exception());
Outputs:
IObservable
2
4
Make sure Exception is hot or published.
Value.SelectMany(v => Exception
.Take(1).Select(e => v))
.Switch();
This will make you get last value when there is no value between two Exception.
Related
I have a table
t:([] s:`GOOG`APPL;d:2?.z.d ;t:2?.z.t)
I'd use = while selecting a single record :
q)select from t where s=`GOOG
s d t
----------------------------
GOOG 2017.01.25 04:30:47.898
However I am expecting an error while selecting multiple records using '=' because I should be using 'in' , but it is returning the correct data rather than throwing any error :
q)select from t where s=`GOOG`APPL
s d t
----------------------------
GOOG 2017.01.25 04:30:47.898
APPL 2007.12.27 04:07:38.923
In the first case you are comparing a vector to an atom. = is overloaded for this operation, so it will compare each element in the vector to that atom
q)t[`s]
`GOOG`APPL
q)t[`s]=`GOOG
10b
In the second case, where you expect the error, = is doing a vector to vector comparison. Since the length of both vectors are the same it works and does not throw a length error :
q)t[`s]=`GOOG`APPL
11b
Changing the order won't return anything due to the element by element comparison :
q)t[`s]=`APPL`GOOG
00b
e.g. for the following table with 3 elements
t:([] s:`GOOG`APPL`HP;d:3?.z.d ;t:3?.z.t)
q)t[`s]
`GOOG`APPL`HP
you'd get a length error
q)t[`s]=`GOOG`APPL
'length
and therefore using in would fix the error
q)t[`s] in `GOOG`APPL
110b
I have two tables
table 1 (orders) columns: (date,symbol,qty)
table 2 (marketData) columns: (date,symbol,close price)
I want to add the close for T+0 to T+5 to table 1.
{[nday]
value "temp0::update date",string[nday],":mdDates[DateInd+",string[nday],"] from orders";
value "temp::temp0 lj 2! select date",string[nday],":date,sym,close",string[nday],":close from marketData";
table1::temp
} each (1+til 5)
I'm sure there is a better way to do this, but I get a 'loop error when I try to run this function. Any suggestions?
See here for common errors. Your loop error is because you're setting views with value, not globals. Inside a function value evaluates as if it's outside the function so you don't need the ::.
That said there's lots of room for improvement, here's a few pointers.
You don't need the value at all in your case. E.g. this line:
First line can be reduced to (I'm assuming mdDates is some kind of function you're just dropping in to work out the date from an integer, and DateInd some kind of global):
{[nday]
temp0:update date:mdDates[nday;DateInd] from orders;
....
} each (1+til 5)
In this bit it just looks like you're trying to append something to the column name:
select date",string[nday],":date
Remember that tables are flipped dictionaries... you can mess with their column names via the keys, as illustrated (very noddily) below:
q)t:flip `a`b!(1 2; 3 4)
q)t
a b
---
1 3
2 4
q)flip ((`$"a","1"),`b)!(t`a;t`b)
a1 b
----
1 3
2 4
You can also use functional select, which is much neater IMO:
q)?[t;();0b;((`$"a","1"),`b)!(`a`b)]
a1 b
----
1 3
2 4
Seems like you wanted to have p0 to p5 columns with prices corresponding to date+0 to date+5 dates.
Using adverb over to iterate over 0 to 5 days :
q)orders:([] date:(2018.01.01+til 5); sym:5?`A`G; qty:5?10)
q)data:([] date:20#(2018.01.01+til 10); sym:raze 10#'`A`G; price:20?10+10.)
q)delete d from {c:`$"p",string[y]; (update d:date+y from x) lj 2!(`d`sym,c )xcol 0!data}/[ orders;0 1 2 3 4]
date sym qty p0 p1 p2 p3 p4
---------------------------------------------------------------
2018.01.01 A 0 10.08094 6.027448 6.045174 18.11676 1.919615
2018.01.02 G 3 13.1917 8.515314 19.018 19.18736 6.64622
2018.01.03 A 2 6.045174 18.11676 1.919615 14.27323 2.255483
2018.01.04 A 7 18.11676 1.919615 14.27323 2.255483 2.352626
2018.01.05 G 0 19.18736 6.64622 11.16619 2.437314 4.698096
I'm trying to obtain the following observable (with a buffer capacity of 10 ticks):
Time 0 5 10 15 20 25 30 35 40
|----|----|----|----|----|----|----|----|
Source A B C D E F G H
Result A E H
B F
C G
D
Phase |<------->|-------|<------->|<------->|
B I B B
That is, the behavior is very similar to the Buffer observable with the difference that the buffering phase is not in precise time slot, but starts at the first symbol pushed in the idle phase. I mean, in the example above the buffering phases start with the 'A', 'E', and 'H' symbols.
Is there a way to compose the observable or do I have to implement it from scratch?
Any help will be appreciated.
Try this:
IObservable<T> source = ...;
IScheduler scheduler = ...;
IObservable<IList<T>> query = source
.Publish(obs => obs
.Buffer(() => obs.Take(1).IgnoreElements()
.Concat(Observable.Return(default(T)).Delay(duration, scheduler))
.Amb(obs.IgnoreElements())));
The buffer closing selector is called once at the start and then once whenever a buffer closes. The selector says "The buffer being started now should be closed duration after the first element of this buffer, or when the source completes, whichever occurs first."
Edit: Based on your comments, if you want to make multiple subscriptions to query share a single subscription to source, you can do that by appending .Publish().RefCount() to the query.
IObservable<IList<T>> query = source
.Publish(obs => obs
.Buffer(() => obs.Take(1).IgnoreElements()
.Concat(Observable.Return(default(T)).Delay(duration, scheduler))
.Amb(obs.IgnoreElements())));
.Publish()
.RefCount();
I'm doing the following:
var count = 0
while(count > 0){
val messages = graph.vertices.flatMap{
// Create messages for other nodes
}
// Cache which is critical for the correct execution
count.cache()
count = messages.count()
val msgType1 = messages.filter()
val msgType2 = messages.filter()
println(count)
//Should be exactly messages.count()
println(msgType1.count() + msgType2.count())
println("---")
}
If I'm executing it exactly like this then the output is:
8
6 2
---
11
3 8
---
0
0 0
---
which add up exactly to the message count.
If I'm removing the count.cache() after the flatMap-operation, then the filtering of the messages is wrong after counting the messages. It looks like the counting clears the messages or something like that.
The output is then:
8
0 0
---
0
0 0
---
Why is that happening? Is it okay that my program only works if I'm using the cache operation at that point or should it also work without caching the messages?
My problem was, that if flatmap() was called once in one loop iteration, then the output was correct.
If it is called twice in one iteration (which could happen, if the messages must be recomputed) then the first output was correct and the following not, because my opertions inside the flatmap() can only be executed one time per node and node multiple times.
So if I call cache() the flatmap is executed only once. Without cache it is called for every count() operation, so the first was correct and the following two wrong.
I read about select statements and its execution steps but I'm not fully understanding what's happening here.
I created two examples of a Fan-In function (from the Go Concurrency Patterns talk)
The first one:
select {
case value := <-g1:
c <- value
case value := <-g2:
c <- value
}
Prints from each channel as expected (each channel keeps its own counter):
Bob : 0
Alice: 0
Bob : 1
Alice: 1
Bob : 2
Alice: 2
Alice: 3
Alice: 4
Bob : 3
Alice: 5
The second one:
select {
case c <- <-g1:
case c <- <-g2:
}
It is randomly selecting a channel and discarding the other one's value:
Bob : 0
Alice: 1
Alice: 2
Alice: 3
Bob : 4
Alice: 5
Bob : 6
Alice: 7
Alice: 8
Bob : 9
Update: while writing this question, I thought the second select was equal to:
var v string
select {
case v = <-g1:
case v = <-g2:
c <- v
}
But I was wrong, because this one always prints from the second channel (as expected from a switch like statement because there isn't fallthrough in select statements):
Bob : 0
Bob : 1
Bob : 2
Bob : 3
Bob : 4
Bob : 5
Bob : 6
Bob : 7
Bob : 8
Bob : 9
Does someone understand why my second example creates a sequence?
Thanks,
Your second select statement is interpreted as:
v1 := <-g1
v2 := <-g2
select {
case c <- v1:
case c <- v2:
}
As described in the language spec, the RHS of each send operator will be evaluated up front when the statement is executed:
Execution of a "select" statement proceeds in several steps:
For all the cases in the statement, the channel operands of receive operations and the channel and right-hand-side expressions of send statements are evaluated exactly once, in source order, upon entering the "select" statement. The result is a set of channels to receive from or send to, and the corresponding values to send. Any side effects in that evaluation will occur irrespective of which (if any) communication operation is selected to proceed. Expressions on the left-hand side of a RecvStmt with a short variable declaration or assignment are not yet evaluated.
If one or more of the communications can proceed, a single one that can proceed is chosen via a uniform pseudo-random selection. Otherwise, if there is a default case, that case is chosen. If there is no default case, the "select" statement blocks until at least one of the communications can proceed.
...
So as step (1) both <-g1 and <-g2 will be evaluated, receiving values from each channel. This may block if there is nothing to receive yet.
At (2), we wait until c is ready to send a value and then randomly choose a branch of the select statement to execute: since they are both waiting on the same channel, they are both ready to proceed.
This explains the behaviour you saw where values are dropped and you got non-deterministic behaviour in which value was sent to c.
If you want to wait on g1 and g2, you will need to use the first form for your statement as you've discovered.
According to [http://golang.org/ref/spec] The Go Programming Language Specification
for { // send random sequence of bits to c
select {
case c <- 0: // note: no statement, no fallthrough, no folding of cases
case c <- 1:
}
}
It'll generate 0 or 1 randomly.
For the second exaple
select {
case c <- <-g1:
case c <- <-g2:
}
when g1 has Bob : 0 and g2 has Alice: 0, either c <- <-g1 or c <- <-g2 will execute , but only one will.
That explain why you have the sequence 0 1 2 3 4 5 6 7 8 9 but not 0 0 1 1 2 2 3 3 4 4
And it also say:
in source order, upon entering the "select" statement. The result is a set of channels to receive from or send to, and the corresponding values to send.
According to my comprehension , even if c <- <-g1 will execute , Alice: 0 also will pop up from g2. So every time you have Bob : i and Alice: i, only one will be printed out.