F#Sliding Window Agent不使用记录

时间:2014-06-18 01:30:08

标签: f# records agent observable

我一直在采样由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) }

1 个答案:

答案 0 :(得分:1)

感谢。看起来像使用System.Reactive更简单的实现,而不是从MSDN for Control.Observable上的文档中的ObservableSource的自定义实现确实按预期工作。但是,那个例子可能存在一些问题。