Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/18.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 我的API全部返回Future[Option[T]],如何在for compr中很好地组合它们_Scala_Scalaz - Fatal编程技术网

Scala 我的API全部返回Future[Option[T]],如何在for compr中很好地组合它们

Scala 我的API全部返回Future[Option[T]],如何在for compr中很好地组合它们,scala,scalaz,Scala,Scalaz,我的所有API方法都返回Future[Option[T]],试图找出如何优雅地执行以下操作: case class UserProfile(user: User, location: Location, addresses: Address) 以下代码当前未编译,因为用户、位置和地址都是选项[user]、选项[location]和选项[address] val up = for { user <- userService.getById(userId) location <-

我的所有API方法都返回Future[Option[T]],试图找出如何优雅地执行以下操作:

case class UserProfile(user: User, location: Location, addresses: Address)
以下代码当前未编译,因为用户、位置和地址都是选项[user]、选项[location]和选项[address]

val up = for {
 user <- userService.getById(userId)
 location <- locationService.getById(locationId)
 address <- addressService.getById(addressId)
} yield UserProfile(user, location, address)
val up=for{

用户为了完整的工作示例,需要一些简单的定义:

import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future

type User = String
type Location = String
type Address = String

case class UserProfile(user: User, location: Location, addresses: Address)

def getUserById(id: Long): Future[Option[User]] = id match {
  case 1 => Future.successful(Some("Foo McBar"))
  case _ => Future.successful(None)
}

def getLocationById(id: Long): Future[Option[Location]] = id match {
  case 1 => Future.successful(Some("The Moon"))
  case _ => Future.successful(None)
}

def getAddressById(id: Long): Future[Option[Address]] = id match {
  case 1 => Future.successful(Some("123 Moon St."))
  case _ => Future.successful(None)
}
为了完整起见,下面是无Scalaz的实现:

def getProfile(uid: Long, lid: Long, aid: Long): Future[Option[UserProfile]] =
  for {
    maybeUser     <- getUserById(uid)
    maybeLocation <- getLocationById(lid)
    maybeAddress  <- getAddressById(aid)
  } yield (
    for {
      user     <- maybeUser
      location <- maybeLocation
      address  <- maybeAddress
    } yield UserProfile(user, location, address)
  )
或者,如果您想要一个
未来[选项[UserProfile]]
您可以调用
run

def getProfile(uid: Long, lid: Long, aid: Long): Future[Option[UserProfile]] = (
  for {
    user     <- OptionT(getUserById(uid))
    location <- OptionT(getLocationById(lid))
    address  <- OptionT(getAddressById(aid))
  } yield UserProfile(user, location, address)
).run
如果任何中间结果为
None
,则整个结果将为
None

scala> getProfile(1L, 1L, 0L).foreach(println)
None

scala> getProfile(0L, 0L, 0L).foreach(println)
None
当然,如果任何一个请求失败,整个过程都会失败,出现第一个错误

作为一个脚注,如果请求彼此不依赖,您可以应用程序而不是一元编写它们:

import scalaz.Scalaz._

def getProfile(uid: Long, lid: Long, aid: Long): Future[Option[UserProfile]] = (
  OptionT(getUserById(uid)) |@|
  OptionT(getLocationById(lid)) |@|
  OptionT(getAddressById(aid))
)(UserProfile.apply _).run

这可以更准确地模拟计算,而且可能更高效,因为它可以并行运行请求。

这就是我所说的全自动运行人,谢谢!|@|就像未来一样。顺序?@Blankman是的,最大的区别是它可以处理不同的类型(同时保持类型和算术).FYI:
Future.onSuccess
已被弃用,因为Scala 2.12@TravisBrown我实际上需要添加另一个调用,但它返回一个Future[Seq[T]]。鉴于上述情况,现在可以添加这个吗?@n4to4更新为使用
foreach
。因为这是关于
option
的明确说明,也许它应该有一个
scalaz
标签(也可能是
monad变压器
和/或
scala猫
)?
scala> getProfile(1L, 1L, 0L).foreach(println)
None

scala> getProfile(0L, 0L, 0L).foreach(println)
None
import scalaz.Scalaz._

def getProfile(uid: Long, lid: Long, aid: Long): Future[Option[UserProfile]] = (
  OptionT(getUserById(uid)) |@|
  OptionT(getLocationById(lid)) |@|
  OptionT(getAddressById(aid))
)(UserProfile.apply _).run