如果我有电子邮件,我想要通过电子邮件获取用户(如果存在)。如果它不存在,我想插入并返回用户。
val userOptFut: Future[Option[User] = emailOpt.map { email =>
userDao.getByEmail(email).map { maybeUserFut =>
maybeUserFut match {
case Some(u) => Future.successful(Some(u))
case None =>
userDao.insert(User(....)) // Future[User]
}
}
}.getOrElse(Future.successful(None))
userDao.getByEmail(..)
返回Future[Option[User]]
我不确定出了什么问题,但出于某种原因,它说我返回Object
而不是用户。
Future [Object]类型的表达式不符合预期的类型 未来[选项[用户]]
以上是什么问题?
答案 0 :(得分:1)
这样的嵌套真的很难在各地正确匹配类型。编译器最终做的是推断它可以使用的最具体的类型,即Object
,并且与您声明的类型不匹配。
将您的功能分解为更小的部分,嵌套级别更少,这样做真的很有帮助,因此类型更难以搞定。我会这样做:
// This is very close to Future.sequence, but Option isn't a subclass
// of TraversableOnce. There's probably an existing function to do
// this in a library like cats or scalaz.
def toFutureOption[A](in: Option[Future[A]]): Future[Option[A]] = in match {
case Some(fut) => fut map {Some(_)}
case None => Future.successful(None)
}
def getOrInsert(email: String): Future[User] =
userDao.getByEmail(email) transformWith {
case Success(Some(user)) => Future.successful(user)
case Success(None) | Failure(_) => userDao.insert(User(email))
}
val userOptFut: Future[Option[User]] =
toFutureOption(emailOpt map getOrInsert)
答案 1 :(得分:0)
您的问题是match
语句的两个分支不会返回相同的类型:
case Some(u) => u // User
case None => userDao.insert(User(....)) // Future[User]
根据您要实现的目标,您可以执行以下操作:
case Some(u) => Future.successful(Some(u))
最后的.getOrElse
可能也不适合您的类型。