F#可观察的滤镜有副作用 [英] F# observable filter with side effect

查看:112
本文介绍了F#可观察的滤镜有副作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有许多事件合并为一个可观察到的执行某些命令的事件.如果命令成功执行,则会产生一些结果.另外,该命令应该被记录.

I have a number of events that are merged into one observable that executes some commands. If a command succeeded some result takes place. In addition, the command should be logged.

就代码而言,这看起来像

In terms of code, this looks like

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

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

where the function exec_action results in some side effect such as editing a treeview. If this succeeded then the property OutlineEdited is set to true.

我希望通过类似的方式来实现

I was hoping to follow this with something like

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

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

but it turns out that Observable.filter is executed once for each subscribed observer. Meaning that the side effect will be repeated.

能否请您提出另一种无需两次执行exec_action即可达到相同结果的方法?我希望尽可能避免使用可变变量.

Can you please suggest another way to achieve the same result without having the exec_action executed twice? I am hoping to avoid having to use a mutable variable if possible.

推荐答案

此示例很好地说明了IObservable<'T>类型(在本示例中通过Observable模块使用)和F#类型IEvent<'T>之间的区别(以及Event模块中的功能).

This example ilustrates nicely the difference between the IObservable<'T> type (used in this example via the Observable module) and the F# type IEvent<'T> (and functions in Event module).

使用 observables 时,每个订阅者都会创建新的操作链(因此,每个订阅者都会执行一次副作用).如果使用 events ,则状态是共享的,副作用仅执行一次(无论订阅者数量如何).另一方面,当您从事件中删除所有订阅者时,这些事件不会被垃圾收集.

When you use observables, every subscriber creates a new chain of operations (so side-effects are executed once for every subscriber). If you use events then the state is shared and side-effects are executed just once (regardless of the number of subscribers). On the other hand, the events do not get garbage collected when you remove all subscribers from an event.

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

So, if you do not need the events to be removed when all subscribers are removed, you should get the behaviour you want just by using Event instead of Observable:

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

这篇关于F#可观察的滤镜有副作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆