Reactive Extensions(RxScala)相当于fold ifEmpty

时间:2015-03-18 08:55:46

标签: scala rx-scala

我想知道是否存在任何与集合和选项相同的Scala fold ifEmpty函数:

fold[B](ifEmpty: => B)(f: (A) => B)

这个函数功能强大,因为它可以在不同的monad类型之间进行转换 - 例如,下面将Option [Person]转换为Observable [Person]:

case class Person(name: String)

val observable = Option(Person("Paddy")).fold
  { Observable.just[Person]() }  // ifEmpty function
  { p => Observable.just(p) }    

我目前的问题是我在Reactive Extensions土地上喜欢类似的东西。我的实际场景调用了更多的#34;如果为空,则调用#34;功能类型 - 理想情况下:

// getFooFromCache returns Observable[Foo] from some cache service
// getFooFromDatabase returns Observable[Foo] from some database service

val sourceObservable = getFooFromCache()
sourceObservable.switchIfEmpty { getFooFromDatabase() }

所以这里的想法是,如果源可观察完成并且什么都不发出,那么"切换"到另一个可观察的。一个实际的例子如上所述 - 尝试从缓存中获取内容,如果没有返回任何内容,则从数据库中获取它。

我目前的解决方法是实现上述目标:

getFooFromCache()
  .map { Option(_) }
  .orElse { None }
  .flatMap {
    case (Some(foo)) => Observable.just(foo)
    case _ => getFooFromDatabase()
  }

换句话说 - 将结果包装在Option中(以便可以将空结果作为None值发出),然后将flatMap与模式匹配一​​起包装。

编辑:如果不存在,我将使用以下几个扩展函数:

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()
        }
    }
  }
}

通过上述我现在可以做到:

getFooFromCache("item.id")
  .switchIfEmpty { () => getFooFromDatabase("item.id") }

1 个答案:

答案 0 :(得分:1)

如果你正在使用RxScala 0.24并且习惯使用"Experimental" APIs,那么你可以

import rx.lang.scala.ExperimentalAPIs._

只是做

getFooFromCache("item.id").switchIfEmpty(getFooFromDatabase("item.id"))

请注意,该参数是热切评估的,因此要获得与解决方法相同的效果,您需要执行此操作

getFooFromCache("item.id").switchIfEmpty(Observable.defer(getFooFromDatabase("item.id")))
<德尔> 我想你想要`orElse [U&gt;:T](默认:⇒U):Observable [U]`  `getFooFromCache(),否则容易(getFooFromDatabase())` (此方法是RxScala所基于的RxJava实现中的`defaultIfEmpty(T)`的[等效](http://reactivex.io/rxscala/comparison.html)。)