gpt4 book ai didi

scala - 错误值 flatMap 不是 Product with Serializable in for with Future[Option] 的成员

转载 作者:行者123 更新时间:2023-12-02 03:01:10 24 4
gpt4 key购买 nike

以下代码块因错误而无法构建:

value flatMap is not a member of Product with Serializable
[error] if (matchingUser.isDefined) {

代码如下:

for {
matchingUser <- userDao.findOneByEmail(email)
user <- {
if (matchingUser.isDefined) {
matchingUser.map(u => {
// update u with new values...
userDao.save(u)
u
})
} else {
val newUser = new User(email)
userDao.create(newUser)
newUser
}
}
} yield user

方法 userDao.findOneByEmail(email) 返回一个Future[Option[User]]对象。
我的 Google 搜索仅关于
EitherwithRightandLeft` 类型。

也许我没有以正确的方式做到这一点,请教我如何正确地做到这一点。

最佳答案

if 语句的第一个分支返回Option[User],另一个分支返回User。因此,整个语句的结果被推断为 Product with Serializable 类型,因为它是两者中唯一的公共(public)父类(super class)型。

您可以将 if 中的最后一条语句包装到 Option 中(只需执行 Option(newUser) 而不是 newUser) 或者,更好的是,使用 fold 而不是整个 if(matchingUser.isDefined) {...} 事情:

 matchingUser.fold { 
val u = new User(email)
userDao.create(u)
u
} { u =>
userDao.save(u)
u
}

这将使该语句的结果成为您可能想要的 Option[User] ... 但它仍然无法编译。问题是你不能在 for-comprehension 中混合不同类型的 monad:因为第一个是 Future,所以所有其他的也必须是。那里不能有 Option

如何解决这个问题?好吧,一种可能性是让 userDao.createuserDao.save 返回它们刚刚保存的对象的 future 。也就是说,一般而言,可能比您拥有的更好,因为现在您要在用户实际存储之前返回用户……如果 create 操作之后失败怎么办?然后你可以像这样重写你的理解:

for {
matchingUser <- userDao.findOneByEmail(email)
user <- matchingUser.fold(userDao.create(new User(email)))(userDao.save)
} yield user

或者干脆完全去掉它(for-comprehension 对于像这样的简单情况来说是一种矫枉过正):

  userDao
.findOneByEmail(email)
.flatMap(_.fold(usrDao.create(new User(email)))(userDao.save))

或者,在这种情况下,使用模式匹配而不是 fold 看起来会更好一些:

 userDao
.findOneByEmail(email)
.flatMap {
case Some(u) => userDao.save(u)
case None => userDao.create(new User(email))
}

关于scala - 错误值 flatMap 不是 Product with Serializable in for with Future[Option] 的成员,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46099932/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com