F# observable filter with side effect

会有一股神秘感。 提交于 2019-12-08 06:40:28

问题


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)

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) []

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

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.


回答1:


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).

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.

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) [] 


来源:https://stackoverflow.com/questions/12874689/f-observable-filter-with-side-effect

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!