Functional unfolds
从这里开始我们将开始介绍第二类方法:unfold方法。
作为一个函数式编程者可能会期望有能力unfold(展开)潜在无限队列,我们要面对的Observable.Create有一个问题是,那就是用它来生成一个infinite sequence(无限队列)可能会比较笨拙。之前的定时器就是无限队列的一个例子,虽然它只是一个简化了的版本,但如果要有效的委托所有工作给System.Timers.Timer类来说仍然有很大的代码量。
此外,前文所介绍的Observable.Create也在最低限度上支持了使用corecursion unfolding队列。
Corecursion
首先来了解一下corecursion的概念。corecursion是一个方法,用于根据当前状态来产生下一个状态。通过传入一个value给corecursion,将函数应用于扩展该值,并使之重复,我们就可以得到一个序列。一个简单的例子就是将1作为种子,并给定递增值为1的函数,可以建立1,2,3,4,5……这样的队列。
用corecursion创建一个IEnumerable <int>队列可以简单的配合yield return语法一起使用,例如下面的例子:
上面的代码可以用来生成这样的自然数序列:
Output:
1st 10 Natural numbers
1
2
3
4
5
6
7
8
9
10
注意,Take(10)用于终止无限序列,这对无限和任意长度的队列非常有用。
Observable.Range
Observable.Range(int, int) 只返回一系列整数,第一个参数是起始值,第2个是个数。下面的例子将会输出10到24然后complete。
Observable.Generate
如果是在同时要遵守代码必须使用惰性求值的原则,又要提供订阅者应有的dispose订阅物资源能力的情况下,使用Observable.Create(因为它返回IObservable<T>对象)来配合Range方法是很困难的,代码量会相当的大。而使用corecursion来提供richer unfold正是为了这种场景而设计的。在RX中,unfold方法,被称为Observable.Generate。
Observable.Generate的简单版本需要以下参数:
初始状态
定义队列应在何种条件下终止的断言
用于为当前状态产生出下一个状态的方法
变换状态到所需输出的方法
下面是使用Observable.Generate来配合Range方法的例子:
Observable.Interval
在本章的前面我们在Observable中用了一个System.Timers.Timer来生成一个continuous消息队列,例子中处理timer的方式并不是在RX中处理timer的首选的方式,RX中提供了现成、首选方法,可以令人满意的替换以下三种底层timer:
System.Timers.Timer
System.Threading.Timer
System.Windows.Threading.DispatcherTimer
通过Schedulers将timer抽象出来,能够让我们为多个平台重用相同的代码。更重要的是能够写独立于平台的代码,使在测试中从多套Schedulers/timer间相互替换变得可能。Schedulers是一个复杂的主题,我们将在之后介绍。
有三种更好的使用恒定时间事件的方法,每一个都是前者的拓展。第一个是Observable.Interval(TimeSpan) ,将从0开始发布增量,此例为每隔一定时间(如下面例子中的250毫秒)发布一次:
Output:
0
1
2
3
4
5
……
一旦订阅,就必须手动dispose来停止队列,因为在本例中这是一个无限队列。
辛苦了!很勤劳!
@eastecho:谢谢支持~
六篇了,坚持写下去啊
@Oncle:谢谢,一定会的。关于RX目前找不到什么系统的中文资料,边学边整理,整理的过程也是加深学习的过程:)
预计会有多少篇?我觉得这边可以整理一下发成主站文章
@eastecho:估计应该在20篇以上?具体还不清楚。主要是一边学习http://www.introtorx.com/一边把它的内容整理翻译过来,如果放主站的话会不会造成什么版权困扰?网站上貌似没有找到什么版权声明,并且我也姑且只是作为个人日志,所以就没多想先放出来了,如果网站要用的话希望不会给你们造成什么麻烦才好。
网站上是总共4章,现在整理出来的进度才到第2章第1小节的一半,最后我也会再重新归纳一遍把文档和思维导图都放出来,如果放成文章不会有什么版权问题的话我也还是推荐等我全部弄完再整理一遍再说会更好一些~
@joey1258:哦,是的,我们自己的所有翻译都是取得授权的。所以目前可能还是个人名义发会比较好。
继续努力! :D