Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala中用于理解的Future[选项]_Scala_Future_For Comprehension - Fatal编程技术网

Scala中用于理解的Future[选项]

Scala中用于理解的Future[选项],scala,future,for-comprehension,Scala,Future,For Comprehension,我有两个函数返回期货。我正试图使用一个屈服理解函数将第一个函数的修改结果输入到另一个函数中 这种方法在以下方面起作用: val schoolFuture = for { ud <- userStore.getUserDetails(user.userId) sid = ud.right.toOption.flatMap(_.schoolId) s <- schoolStore.getSchool(sid.get) if sid.isDefined }

我有两个函数返回期货。我正试图使用一个屈服理解函数将第一个函数的修改结果输入到另一个函数中

这种方法在以下方面起作用:

  val schoolFuture = for {
    ud <- userStore.getUserDetails(user.userId)
    sid = ud.right.toOption.flatMap(_.schoolId)
    s <- schoolStore.getSchool(sid.get) if sid.isDefined
  } yield s
val schoolFuture=for{
ud(编辑以给出正确答案!)

这里的关键是
未来
选项
不要在
中为
组合,因为没有正确的
平面图
签名。提醒一下,对于这样的德苏加:

for ( x0 <- c0; w1 = d1; x1 <- c1 if p1; ... ; xN <- cN) yield f
c0.flatMap{ x0 => 
  val w1 = d1
  c1.filter(x1 => p1).flatMap{ x1 =>
    ... cN.map(xN => f) ... 
  }
}
要将一个
选项
变成一个已经完成的
未来

for {
  ud <- userStore.getUserDetails(user.userId)  // RHS is a Future[Either[...]]
  sid = ud.right.toOption.flatMap(_.schoolId)  // RHS is an Option[Int]
  fid <- sid.map(Future.successful).getOrElse(Future.failed(new Exception))  // RHS is Future[Int]
  s <- schoolStore.getSchool(fid)
} yield s
然后,突然之间,对理解的要求又变得合理了:

for {
  ud <- userStore.getUserDetails(user.userId)
  sid <- ud.right.toOption.flatMap(_.schoolId).future
  s <- schoolStore.getSchool(sid)
} yield s
用于{
ud关于
Promise[Option[a]]
的类似问题可能会有所帮助。只需用
Future
代替
Promise

我根据您的问题推断出
getUserDetails
getSchool
的以下类型:

getUserDetails: UserID => Future[Either[??, UserDetails]]
getSchool: SchoolID => Future[Option[School]]
由于忽略了
中的故障值,将其转换为
选项
,因此实际上有两个类型为
A=>Future[Option[B]]
的值

一旦你有了
Future
Monad
实例(其中可能有一个,或者你可以按照我链接的答案编写自己的),将
OptionT
转换器应用于你的问题就会像这样:

for {
  ud  <- optionT(getUserDetails(user.userID) map (_.right.toOption))
  sid <- optionT(Future.successful(ud.schoolID))
  s   <- optionT(getSchool(sid))
} yield s
用于{

ud如果
选项[School]
None
,您希望发生什么行为?您希望未来失败吗?有什么例外?您希望它永远不会完成吗?(听起来是个坏主意)

无论如何,for表达式中的
if
子句将调用
filter
方法

如果当前未来包含满足谓词的值, 新的未来也将保持这种价值。否则,结果 未来将以一种非接触式的例外而失败

但是等等:

scala> None.get
java.util.NoSuchElementException: None.get
正如您所看到的,None.get返回完全相同的内容

因此,如果定义了sid.isDefined
,那么就应该去掉
,这应该会返回一个合理的结果:

  val schoolFuture = for {
    ud <- userStore.getUserDetails(user.userId)
    sid = ud.right.toOption.flatMap(_.schoolId)
    s <- schoolStore.getSchool(sid.get)
  } yield s
val schoolFuture=for{

ud我们在Future[Option[T]]上做了一个小包装器,它的作用类似于一个monad(甚至没有人检查monad定律,但有map、flatMap、foreach、filter等等)。它的作用远不止一个异步选项

那里有很多难闻的代码,但至少作为一个例子,它可能是有用的。
顺便说一句:有很多开放性问题(例如)

它更容易使用
https://github.com/qifun/stateless-future
https://github.com/scala/async
要执行
A-Normal-Form
转换。

这给了我一个编译错误。发现:scala.concurrent.Future[Option[com.authorpub.userservice.School]]必需:选项[?]s您能解释一下您所有的类型是什么吗?考虑到您还没有发布完整的工作代码,有点难说。未来是什么,工作代码中的选项是什么?如果您这样做,您可以让Scala 2.10打印出表达式的类型:
import Scala.reflect.runtime.universe.\u;def typeme[A:TypeTag](A:A)={println(隐式[TypeTag[A]]);A}
然后将表达式包装在
typeme
中,例如
sid=typeme(ud.right.toOption.flatMap(u.schoolID))
。有人未经评论就投了反对票。这不是很有用。现在的答案有什么问题吗?我更喜欢本·詹姆斯的答案。虽然Scalaz、Monads和所有这些东西让很多人感到害怕,但事实上这些概念非常简单。Scalaz已经有了解决问题所需的所有抽象。相反,这个answer引入了一个新概念
OptionIsFuture
,我认为它类似于monad transformer。诚然,scalaz让我有点害怕,我仍然有办法继续学习。这解决了我认为可以解决的问题。谢谢!谢谢你的回答,但是到scalaz contrib库的链接断开了。你不需要d
scalaz contrib不再
,因为Monad的未来实例现在由scalaz自己通过混合
FutureInstances
特性来提供。对于不需要scalaz;)的解决方案,+1
for {
  ud <- userStore.getUserDetails(user.userId)
  sid <- ud.right.toOption.flatMap(_.schoolId).future
  s <- schoolStore.getSchool(sid)
} yield s
getUserDetails: UserID => Future[Either[??, UserDetails]]
getSchool: SchoolID => Future[Option[School]]
for {
  ud  <- optionT(getUserDetails(user.userID) map (_.right.toOption))
  sid <- optionT(Future.successful(ud.schoolID))
  s   <- optionT(getSchool(sid))
} yield s
scala> None.get
java.util.NoSuchElementException: None.get
  val schoolFuture = for {
    ud <- userStore.getUserDetails(user.userId)
    sid = ud.right.toOption.flatMap(_.schoolId)
    s <- schoolStore.getSchool(sid.get)
  } yield s