我们有一个Scala / Play应用程序,其中有几个隐式类可以从Request创建Try对象,例如
implicit class RequestUtils[+T](req: Request[T]) {
def user: Try[User] = // pull the User from the Session, or throw an UnauthorizedException
def paging: Try[Paging] = // create a Paging object, or throw an IllegalArgumentException
}
然后我们通过flatMaps
访问包装的对象def route(pathParam: String) = BasicAction {
request =>
request.user.flatMap(user =>
request.paging.flatMap(paging =>
Try{ ... }
))}
最后,ActionBuilder从Try
生成SimpleResultcase class BasicRequest[A](request: Request[A]) extends WrappedRequest(request)
class BasicActionBuilder extends ActionBuilder[BasicRequest] {
def invokeBlock[A](request: Request[A], block: (BasicRequest[A]) => Future[SimpleResult]) = {
block(BasicRequest(request))
}
}
def BasicAction[T](block: BasicRequest[AnyContent] => Try[T]) = {
val f: BasicRequest[AnyContent] => SimpleResult = (req: BasicRequest[AnyContent]) =>
block(req) match {
case Success(s) => Ok(convertToJson(s))
case Failure(e: UnauthorizedException) => Unauthorized(e.getMessage)
case Failure(e: Exception) => BadRequest(e.getMessage)
case Failure(t: Throwable) => InternalServerError(e.getMessage)
}
val ab = new BasicActionBuilder
ab.apply(f)
}
我们试图找到一种基本上将多个Try对象组合在一起的方法(或者沿着这些方向的东西 - 我们不会使用Trys) - flatMaps对于一个或两个Trys工作正常,但是嵌套它们更多比这阻碍了程序的可读性。我们可以手动组合对象,例如
case class UserAndPaging(user: User, paging: Paging)
implicit class UserAndPagingUtils[+T](req: Request[T]) {
def userAndPaging: Try[UserAndPaging] = req.user.flatMap(user => req.paging.flatMap(paging => UserAndPaging(user, paging))
}
但这会导致案例类+隐式类定义组合爆炸。理想情况下,我希望能够以临时方式组合多个Try对象,例如
def route(pathParam: String) = BasicAction {
request => compose(request.user, request.paging).flatMap(userWithPaging => ...)
}
并为我做了一个神奇的尝试[用户分页],但我不知道我是怎么做的 - 我一直在努力尝试为类型系统分配一个有意义的类型来“编写” “没有任何成功。
如何将多个Try对象组合在一起,或者使用另一种语言构造等效?
答案 0 :(得分:6)
Try
可以是used in for-comprehensions,因为它们具有flatMap
功能:
def route(pathParam: String) = BasicAction { request =>
val userWithPaging =
for {
user <- request.user
paging <- request.paging
} yield {
doSomethingWith(user, paging)
}
}