考虑到反应式编程,我经常会遇到两个流相互依赖的情况.解决这些案件的惯用方法是什么?

一个最小的例子:有按钮A和B,都显示一个值.单击A必须将A的值增加B.单击B必须将B的值设置为A.

我能提出的第一个解决方案(F#中的示例,但欢迎使用任何语言的答案):

let solution1 buttonA buttonB =
    let mutable lastA = 0
    let mutable lastB = 1
    let a = new Subject<_> ()
    let b = new Subject<_> ()
    (OnClick buttonA).Subscribe(fun _ -> lastA <- lastA + lastB; a.OnNext lastA) 
    (OnClick buttonB).Subscribe(fun _ -> lastB <- lastA; b.OnNext lastB)
    a.Subscribe(SetText buttonA)
    b.Subscribe(SetText buttonA)
    a.OnNext 0
    b.OnNext 1

这个解决方案使用可变状态和主题,它不是非常易读并且看起来不惯用.

我尝试的第二个解决方案涉及创建一个将两个依赖流链接在一起的方法:

let dependency (aGivenB: IObservable<_> -> IObservable<_>) (bGivenA: IObservable<_> -> IObservable<_>) =
    let bProxy = new ReplaySubject<_> () 
    let a = aGivenB bProxy
    let b = bGivenA a
    b.Subscribe(bProxy.OnNext)
    a,b

let solution2 buttonA buttonB =
    let aGivenB b =
        Observable.WithLatestFrom(OnClick buttonA,b,fun click bValue -> bValue)
                  .Scan(fun acc x -> acc + x)
                  .StartWith(0)
    let bGivenA a =
        Observable.Sample(a,OnClick buttonB)
                  .StartWith(1)
    let a,b = dependency aGivenB bGivenA
    a.Subscribe(SetText buttonA)
    b.Subscribe(SetText buttonB)

这看起来好一点,但由于在反应库中不存在类似依赖的方法,我相信存在更惯用的解决方案.使用第二种方法也很容易引入无限递归.

建议的方法是解决涉及流之间循环依赖的问题,例如上面的例子,在反应式编程中?

解决方法

编辑:

这是一个F#解决方案:

type DU = 
    | A 
    | B 

type State = { AValue : int; BValue : int }

let solution2 (aObservable:IObservable<_>,bObservable:IObservable<_>) = 

    let union = aObservable.Select(fun _ -> A).Merge(bObservable.Select(fun _ -> B))

    let result = union.Scan({AValue = 0; BValue = 1},fun state du -> match du with
        | A -> { state with AValue = state.AValue + state.BValue }
        | B -> { state with BValue = state.AValue }
    )

    result

由于内置的​​歧视联盟和记录,F#实际上是一种很好的语言.这是一个用C#编写的答案,带有一个自定义的discriminated Union;我的F#相当生疏.

诀窍是使用区别联合将您的两个可观察对象转换为一个可观察对象.因此,基本上将a和b合并为一个受歧视联盟的可观察者:

a : *---*---*---**
b : -*-*--*---*---
du: ab-ba-b-a-b-aa

完成后,您可以对项目是’A’推送还是’B’推送做出反应.

为了确认,我认为没有办法明确设置ButtonA / ButtonB中嵌入的值.如果存在,那些变化应该被建模为可观察的,并且也会受到歧视的联合.

var a = new Subject<Unit>();
var b = new Subject<Unit>();
var observable = a.discriminatedUnion(b)
    .Scan(new State(0,1),(state,du) => du.unify(
        /* A clicked case */_ => new State(state.A + state.B,state.B),/* B clicked case */_ => new State(state.A,state.A)
    )
);

observable.Subscribe(state => Console.WriteLine($"a = {state.A},b = {state.B}"));
a.OnNext(Unit.Default);
a.OnNext(Unit.Default);
a.OnNext(Unit.Default);
a.OnNext(Unit.Default);
b.OnNext(Unit.Default);
a.OnNext(Unit.Default);
a.OnNext(Unit.Default);
a.OnNext(Unit.Default);
a.OnNext(Unit.Default);
b.OnNext(Unit.Default);

这是C#中依赖的类.其中大部分内容很容易转换为内置的F#类型.

public class State /*easily replaced with an F# record */
{
    public State(int a,int b)
    {
        A = a;
        B = b;
    }

    public int A { get; }
    public int B { get; }
}

/* easily replaced with built-in discriminated unions and pattern matching */
public static class discriminatedUnionExtensions
{
    public static IObservable<discriminatedUnionClass<T1,T2>> discriminatedUnion<T1,T2>(this IObservable<T1> a,IObservable<T2> b)
    {
        return Observable.Merge(
            a.Select(t1 => discriminatedUnionClass<T1,T2>.Create(t1)),b.Select(t2 => discriminatedUnionClass<T1,T2>.Create(t2))
        );
    }

    public static IObservable<TResult> unify<T1,T2,TResult>(this IObservable<discriminatedUnionClass<T1,T2>> source,Func<T1,TResult> f1,Func<T2,TResult> f2)
    {
        return source.Select(union => unify(union,f1,f2));
    }

    public static TResult unify<T1,TResult>(this discriminatedUnionClass<T1,T2> union,TResult> f2)
    {
        return union.Item == 1
            ? f1(union.Item1)
            : f2(union.Item2)
        ;
    }
}

public class discriminatedUnionClass<T1,T2>
{
    private readonly T1 _t1;
    private readonly T2 _t2;
    private readonly int _item;
    private discriminatedUnionClass(T1 t1,T2 t2,int item)
    {
        _t1 = t1;
        _t2 = t2;
        _item = item;
    }

    public int Item
    {
        get { return _item; }
    }

    public T1 Item1
    {
        get { return _t1; }
    }

    public T2 Item2
    {
        get { return _t2; }
    }

    public static discriminatedUnionClass<T1,T2> Create(T1 t1)
    {
        return new discriminatedUnionClass<T1,T2>(t1,default(T2),1);
    }

    public static discriminatedUnionClass<T1,T2> Create(T2 t2)
    {
        return new discriminatedUnionClass<T1,T2>(default(T1),t2,2);
    }
}

c# – 在响应式编程中循环之间的依赖关系的更多相关文章

  1. 吃透移动端 Html5 响应式布局

    这篇文章主要介绍了吃透移动端 Html5 响应式布局,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

  2. 如何在iOS上快速将ALAsset映像保存到磁盘?

    我正在使用ALAsset来检索这样的图像:这返回CGImageRef,我想尽快保存到磁盘…解决方案1:解决方案2:问题是两种方法在设备上的执行速度都很慢.每张图片大约需要2秒才能执行此操作.这绝对是长久的.问题:如何加快图像保存过程?或许还有更好的解决方案吗?

  3. ios – 根据大小类更改约束的乘数

    根据当前的大小类,可以给出一个不同乘数的约束吗?我有一个看法,我想要的是一般尺寸类宽度的一半的屏幕尺寸,我希望它是一个紧凑的尺寸类宽度的屏幕尺寸的80%.在故事板中,我可以选择将不同大小的类别的不同变量添加到约束常量值,但不是乘数值.这是相等的宽度限制.我没有在程序上添加约束,所以我希望他们可能是一个解决方案,在这条路上.任何人都可以告诉我是否可以通过故事板或编程方式来做我正在寻找的内容?

  4. ios – 线条图线与自身的交点,也可以检测绘制线内的CCSprites

    一旦你找到一个命中,使用确切的点和点的历史来构造一个多边形.从那里你应该能够执行一个“多边形点”测试.一些表现提示:>在搜索交叉点时,只检查最新的线段与其他线段的冲突>当您可以断定两点在线段的一个极端时,您可以跳过段,例如:current.a.x

  5. 是否可以从我的iOS应用程序包中删除文件?

    解决方法无法删除捆绑包中的文件.必须对应用程序进行签名,如果以任何方式修改了包,它将不会通过签名.我能想到的唯一其他解决方案是设置Web服务,并让您的应用程序根据需要下载部分内容.这可能是也可能不是可行的解决方案,具体取决于您的应用实际执行的操作.

  6. Swift40/90Days - 用函数式编程解决逻辑难题

    Swift90Days-用函数式编程解决逻辑难题这篇翻译的文章,用两种方法解决了同一个逻辑难题。第二种方法利用了Swift的一些语言特性,实现了函数式编程的解决方案。这样的代码对于指令式编程来说再平常不过,接下来我们就来看下如何用函数式编程解决这个问题。Swift中函数已经是一等公民,这让高阶函数变成可能,也就是说,一个函数可以是通过其它函数组装构成的。思考Swift对于函数式编程的支持让我感觉的兴奋,Excited!

  7. 关于oc和swift混编 框架framework时 只能在真机运行或只能在模拟器单独运行的解决方案

    问题描述:关于oc和swift混编框架framework时只能在真机运行或只能在模拟器单独运行的解决方案。

  8. tableview 最上面有空白 解决方案

    self.automaticallyAdjustsScrollViewInsets=false

  9. 比较 – Swift:如何找出字母是字母数字还是数字

    我想在以下字符串中计算字母,数字和特殊字符的数量:我试过了:但我收到错误。我尝试了各种其他变体–仍然会收到错误–例如:任何线索?可能的Swift解决方案:更新:上述解决方案仅适用于ASCII字符集中的字符,即不识别,é或为字母。以下替代方案解决方案从Foundation框架中使用NSCharacterSet,它可以测试字符基于他们的Unicode字符类:更新2:从Xcode6beta4开始,第一个解决方案不再工作,因为从Swift中删除了isAlpha()和相关的方法。

  10. swift – 我可以指定generic是值类型吗?

    我知道我们可以通过使用AnyObject来基本上指定我们的泛型是任何引用类型:但是有没有办法指定我们的泛型应该只是值类型,不允许引用类型?

随机推荐

  1. c# – (wpf)Application.Current.Resources vs FindResource

    所以,我正在使用C#中的WPF创建一个GUI.它看起来像这样:它现在还没有完成.这两行是我尝试制作一种数据表,它们在XAML中是硬编码的.现在,我正在C#中实现添加新的水果按钮功能.我在XAML中有以下样式来控制行的背景图像应该是什么样子:因此,在代码中,我为每列col0,col1和col2创建一个图像,如果我使用以下代码,它添加了一个如下所示的新行:如你所见,它不太正确……为什么一个似乎忽略了一些属性而另一个没有?

  2. c# – 绑定DataGridTemplateColumn

    似乎我已经打了个墙,试图在DataGrid上使用DataTemplates.我想要做的是使用一个模板来显示每个单元格的两行文本.但是似乎无法以任何方式绑定列.以下代码希望显示我想做的事情.注意每个列的绑定:模板列没有这样的东西,因此,这个xaml不可能工作.我注定要将整个DataTemplate复制到每个列,只是对每个副本都有不同的约束?解决方法我不完全确定你想要做什么,但如果您需要获取整行的DataContext,可以使用RelativeSource绑定来移动视觉树.像这样:

  3. c# – 学习设计模式的资源

    最近我来到了这个设计模式的概念,并对此感到非常热情.你能建议一些帮助我深入设计模式的资源吗?

  4. c# – 是否有支持嵌入HTML页面的跨操作系统GUI框架?

    我想开发一个桌面应用程序来使用跨系统,是否有一个GUI框架,允许我为所有3个平台编写一次代码,并具有完全可脚本化的嵌入式Web组件?我需要它有一个API来在应用程序和网页之间进行交流.我知道C#,JavaScript和一些python.解决方法Qt有这样的事情QWebView.

  5. c# – 通过字符串在对象图中查找属性

    我试图使用任意字符串访问嵌套类结构的各个部分.给出以下(设计的)类:我想要从Person对象的一个实例的“PersonsAddress.HousePhone.Number”获取对象.目前我正在使用反思来做一些简单的递归查找,但是我希望有一些忍者有更好的想法.作为参考,这里是我开发的(crappy)方法:解决方法您可以简单地使用标准的.NETDataBinder.EvalMethod,像这样:

  6. c# – 文件下载后更新页面

    FamilyID=0a391abd-25c1-4fc0-919f-b21f31ab88b7&displaylang=en&pf=true它呈现该页面,然后使用以下元刷新标签来实际向用户提供要下载的文件:你可能需要在你的应用程序中做类似的事情.但是,如果您真的有兴趣在文件完全下载后执行某些操作,那么您的运气不佳,因为没有任何事件可以与浏览器进行通信.执行此操作的唯一方法是上传附件时使用的AJAXupload.

  7. c# – 如何在每个机器应用程序中实现单个实例?

    我必须限制我的.net4WPF应用程序,以便每台机器只能运行一次.请注意,我说每个机器,而不是每个会话.我使用一个简单的互斥体实现单实例应用程序,直到现在,但不幸的是,这样一个互斥是每个会话.有没有办法创建机器互连,还是有其他解决方案来实现每个机器应用程序的单个实例?

  8. c# – WCF和多个主机头

    我的雇主网站有多个主机名,都是同一个服务器,我们只是显示不同的皮肤来进行品牌宣传.不幸的是,在这种情况下,WCF似乎不能很好地工作.我试过overridingthedefaulthostwithacustomhostfactory.这不是一个可以接受的解决方案,因为它需要从所有主机工作,而不仅仅是1.我也看过thisblogpost,但是我无法让它工作,或者不是为了解决我的问题.我得到的错误是“这

  9. c# – ASP.NET MVC模型绑定与表单元素名称中的虚线

    我一直在搜索互联网,试图找到一种方式来容纳我的表单元素的破折号到ASP.NET的控制器在MVC2,3或甚至4中的默认模型绑定行为.作为一名前端开发人员,我更喜欢在我的CSS中使用camelCase或下划线进行破折号.在我的标记中,我想要做的是这样的:在控制器中,我会传入一个C#对象,看起来像这样:有没有办法通过一些正则表达式或其他行为来扩展Controller类来适应这种情况?我讨厌这样的事实,我必须这样做:甚至这个:思考?

  10. c# – 用户界面设计工具

    我正在寻找一个用户界面设计工具来显示文档中可能的GUI.我不能生成代码.我知道MicrosoftVisio提供了一个功能.但有什么办法吗?您使用哪种软件可视化GUI?

返回
顶部