我一直在采样由Tomas Petricek编写的F#片段,它返回一个可观察到的滑动窗口 包含从输入可观察对象中提取的元素。当传递给函数的IObservable包含int或元组时,它可以正常工作,但是如果它是一个IObservable记录,那么'count'元素的每个结果数组(窗口)都包含相同的值。并且每个新窗口包含与观察到的最后一个值相同的“count”元素。该片段在下面复制。异步表达式内部是否存在可能导致此行为的F#记录?
open System
module Observable =
/// Returns an observable that yields sliding windows of
/// containing elements drawn from the input observable.
/// Each window is returned as a fresh array.
let windowed (count:int) (source:IObservable<_>) =
{ new IObservable<_> with
member x.Subscribe(observer) =
// Start an agent that remembers partial windows of length
// smaller than the count (new agent for every observer)
let agent = MailboxProcessor.Start(fun agent ->
// The parameter 'lists' contains partial lists and their lengths
let rec loop lists = async {
// Receive the next value
let! value = agent.Receive()
// Add new empty list and then the new element to all lists.
// Then split the lists into 'full' that should be sent
// to the observer and 'partial' which need more elements.
let full, partial =
((0, []) :: lists)
|> List.map (fun (length, l) -> length + 1, value::l)
|> List.partition (fun (length, l) -> length = count)
// Send all full lists to the observer (as arrays)
for (_, l) in full do
observer.OnNext(l |> Array.ofSeq |> Array.rev)
// Continue looping with incomplete lists
return! loop partial }
// Start with an empty list of partial lists
loop [])
// Send incoming values to the agent
source.Subscribe(agent.Post) }
答案 0 :(得分:1)
感谢。看起来像使用System.Reactive更简单的实现,而不是从MSDN for Control.Observable上的文档中的ObservableSource的自定义实现确实按预期工作。但是,那个例子可能存在一些问题。