如何重构我的代码,以便在表达式中没有if语句?
我收到执行异常:
[NoSuchElementException: Future.filter predicate is not satisfied]
我正在做一个if选项,定义如下,导致问题:
val maybeUserFut: Future[Option[User]] =
for {
usernameOpt <- lookupUsername("...")
if usernameOpt.isDefined
userOpt <- getUser(usernameOpt.get)
} userOpt
我应该开始使用哪种模式来避免此错误?
答案 0 :(得分:0)
for {
usernameOpt <- lookupUsername("...")
if usernameOpt.isDefined
userOpt <- getUser(usernameOpt.get)
} yield userOpt
转化为
lookupUsername("...")
.withFilter({ usernameOpt => usernameOpt.isDefined })
.flatMap({ usernameOpt =>
getUser(usernameOpt.get).map({ userOpt =>
userOpt
})
})
Future.withFilter
定义为(source):
def filter(p: T => Boolean)(implicit executor: ExecutionContext): Future[T] =
map {
r => if (p(r)) r else throw new NoSuchElementException("Future.filter predicate is not satisfied")
}
所以没有简单的转换可以发挥作用。
我可能会写一些类似的东西:
lookupUsername("...").flatMap({ usernameOpt =>
usernameOpt match {
case None => Future.successful(None)
case Some(username) => getUser(username)
}
})
如果你想使用for
理解语法,你需要一个像Scalaz OptionT这样的monad变换器,它将显式提升抽象为Future
(例如case None => Future.successful(None)
):
import scalaz._
import Scalaz._
import scalaz.OptionT._
val maybeUserFut: Future[Option[User]] =
(for {
username <- optionT(lookupUsername("..."))
user <- optionT(getUser(username))
} yield user).run