0

我想知道是否有任何等效的 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 领域有类似的东西。我的实际场景更多地需要“如果为空则切换”类型的功能 - 理想情况下:

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

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

所以这里的想法是,如果源 observable 完成并且什么都不发出,那么“切换”到另一个 observable。上面建议的一个实际示例 - 尝试从缓存中获取某些内容,如果没有返回任何内容,则从数据库中获取它。

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

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") }
4

1 回答 1

1

如果您使用的是 RxScala 0.24 并且习惯于使用“实验性”API,那么您可以

import rx.lang.scala.ExperimentalAPIs._

然后做

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

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

getFooFromCache("item.id").switchIfEmpty(Observable.defer(getFooFromDatabase("item.id")))
我想你想要 `orElse[U >: T](default: ⇒ U): Observable[U]` `getFooFromCache().orElse(getFooFromDatabase())` (这个方法是 [equivalent](http://reactivex .io/rxscala/comparison.html) 的 `defaultIfEmpty(T)` 在 RxScala 所基于的 RxJava 实现中。)
于 2015-03-18T10:56:51.387 回答