Reactive Extensions (RxScala) equivalent of fold ifEmpty
我想知道是否存在与Scala折叠ifEmpty函数等效的集合和选项:
1 | fold[B](ifEmpty: => B)(f: (A) => B) |
此功能强大,因为它可以在不同的monad类型之间进行转换-例如,以下代码将Option [Person]转换为Observable [Person]:
1 2 3 4 5 |
我当前的问题是我希望在Reactive Extensions领域中找到类似的东西。我的实际情况更多地要求"空时切换"类型的功能-理想情况是:
1 2 3 4 5 | // getFooFromCache returns Observable[Foo] from some cache service // getFooFromDatabase returns Observable[Foo] from some database service val sourceObservable = getFooFromCache() sourceObservable.switchIfEmpty { getFooFromDatabase() } |
因此这里的想法是,如果源可观察对象完成并且什么也不发出,则"切换"到另一个可观察对象。如上面所建议的,是一个实际的示例-尝试从缓存中获取某些内容,如果没有返回任何内容,则从数据库中获取它。
我目前实现上述目标的解决方法如下:
1 2 3 4 5 6 7 |
换句话说-将结果package在Option中(以便可以将空结果作为None值发出),然后是带有模式匹配的flatMap。
编辑:如果不存在,这是我将使用的几个扩展功能:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | object RxUtils { implicit class RxUtilExtensions[+T](val observable: Observable[T]) extends AnyVal { def toOption[U >: T]() : Observable[Option[U]] = { observable .map { Option(_) } .orElse { None } } def switchIfEmpty[U >: T](f: () => Observable[U]) : Observable[U] = { observable.toOption .flatMap { case(Some(t)) => Observable.just(t) case _ => f() } } } } |
通过上面的操作,我现在可以做到:
1 2 | getFooFromCache("item.id") .switchIfEmpty { () => getFooFromDatabase("item.id") } |
如果您使用的是RxScala 0.24,并且对使用"实验性" API感到满意,则可以
1 |
然后做
1 | getFooFromCache("item.id").switchIfEmpty(getFooFromDatabase("item.id")) |
请注意,该参数已被急切地评估,因此,要获得与您的解决方法相同的效果,您将需要执行
1 | getFooFromCache("item.id").switchIfEmpty(Observable.defer(getFooFromDatabase("item.id"))) |
我认为您需要`orElse [U>:T](默认值:?U):Observable [U]`
`getFooFromCache()。orElse(getFooFromDatabase())`
(此方法是RxScala所基于的RxJava实现中的defaultIfEmpty(T)的[equivalent](http://reactivex.io/rxscala/comparison.html)。
del>