我相信您上述问题的答案是您最初的假设可能是错误的。我相信可观察序列(更多)类似于行为和信号(随连续时间变化,可以/是无限的,默认情况下是同步的)。Conal 似乎表明事件是某个时间点的特定状态,“正在发生”,例如“描述时间 t0 后第一次左键按下的事件”[*1]
|Rx |Conal |ELM |
|--------------|--------|------|
|T |Event | ? |
|IObservable<T>|Behavior|Signal|
我相信 Conal 描述中的 Event 是某个时间点的实际值。所以更具体,我认为这更准确
|Rx |Conal |ELM |
|---------------------------|--------|------|
|TimeStamp<T> |Event | ? |
|ReplaySubject<TimeStamp<T>>|Behavior|Signal|
我相信这里ReplaySubject<TimeStamp<T>>
更接近地代表了我所理解的行为(包含状态和时间,可以在某个时间点获取值)。但是,由于 aReplaySubject
并不能真正让您从某个时间点拉出状态,因此它们并不是完全一致的。在我看来,EventStore 是更接近的匹配。
所以要明确一点,在我的理解中,可观察序列 (Rx IObservable<T>
) 和 Conal 的行为在某种程度上共享相似的定义。它们都表示随着时间的推移有序的值序列。然而在 Rx 中,这都是一个可观察的序列。请记住,Rx 纯粹是一个允许您查询事件流的库。有一些功能允许您缓存数据 ( Replay
/ Buffer
) 或使用数据窗口 ( Window
/ GroupJoin
),您甚至可以使用时间戳 ( TimeStamp
/ TimeInterval
) 丰富数据。
然而,Conal 的行为与可观察序列的不同之处在于它的持久性和历史查询的特性。据我了解,除了 Rx 的功能外,Conal 的行为还指定您能够在任何给定时间点提取序列的值。例如,在时间 00:00:01 的价格变动为 1.23 美元,然后在时间 00:00:05 的另一个价格变动为 2.34 美元,消费者可以在时间 00:00:02 要求一个价值,并会得到返回 1.23 美元的值(该时间点的最新值)。
time [t1 ] [t2] [t3] [t4] [t5 ]
prices ----[$1.23]--------------------[$2.34]--->
price@t2 -------------[$1.23]|
Rx 不为此提供任何支持,但可以不遗余力地编写自定义运算符来支持这一点。
//A forced example of querying historical data.
// Be carefull as Replay() uses an unbounded buffer!
var source = Observable.Interval(TimeSpan.FromMilliseconds(250))
.Timestamp()
.Replay();
var connection = source.Connect();
var time2 = DateTimeOffset.Now+TimeSpan.FromSeconds(2);
var valueAtTime2 = source.TakeWhile(ts=>ts.Timestamp <= time2)
.LastAsync();
valueAtTime2.Dump(); //LinqPad feature to output the result
可以(可能?)支持这种追溯查询的系统可以是 CEP(复杂事件处理)引擎或 EventStore 样式数据库等系统。
[*1]。http://conal.net/papers/icfp97/icfp97.pdf