【问题标题】:F# observable filter with side effect具有副作用的 F# 可观察过滤器
【发布时间】:2012-10-13 15:47:55
【问题描述】:

我有许多事件被合并到一个执行某些命令的 observable 中。如果命令成功,则会产生一些结果。此外,还应记录该命令。

就代码而言,这看起来像

    let mevts = modifyingevents |> Observable.filter exec_action
                    |> Observable.add (fun action -> self.OutlineEdited <- true)

函数exec_action 会产生一些副作用,例如编辑树视图。如果成功,则属性 OutlineEdited 设置为 true

我希望用类似的东西来跟进这个

    mevts |> Observable.scan (fun log action -> action::log) []

但事实证明Observable.filter每个订阅的观察者 执行一次。意味着副作用会重复。

您能否建议另一种方法来实现相同的结果,而无需执行两次 exec_action?我希望尽可能避免使用可变变量。

【问题讨论】:

  • 您可以让exec_action 在内部对lazy 进行操作,以便仅在第一次执行时进行评估。

标签: f# observable frp


【解决方案1】:

这个例子很好地说明了IObservable&lt;'T&gt; 类型(在这个例子中通过Observable 模块使用)和F# 类型IEvent&lt;'T&gt;(以及Event 模块中的函数)之间的区别。

当您使用 observables 时,每个订阅者都会创建一个新的操作链(因此每个订阅者都会执行一次副作用)。如果你使用 events,那么状态是共享的,副作用只执行一次(不管订阅者的数量)。另一方面,当您从 事件 中删除所有订阅者时,事件不会被垃圾回收。

因此,如果您不需要在删除所有订阅者时删除事件,您应该使用Event 而不是Observable 来获得您想要的行为:

modifyingevents 
|> Event.filter exec_action 
|> Event.scan (fun log action -> action::log) [] 

【讨论】:

  • 完美运行!我想这引出了一个问题:如果我想要共享状态的垃圾收集怎么办。我现在不需要那个,所以我想我会留到另一天。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-11-19
  • 1970-01-01
  • 2020-09-05
  • 2020-09-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多