我想知道是否存在任何与集合和选项相同的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") }
答案 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)。)
德尔>