for之后如何避免平面图
How to avoid the flatmap after for
我有以下代码片段:
(for {
_ <- LiveUserQuery.make(DbManager.failRollback).create(user)
- <- IO.sleep(2.seconds)
a <- router.run(Request(GET, uri"/user/d85ec250-bb5c-11ea-b3de-0242ac130030")).value
} yield a).flatMap {
case Some(req) =>
req.as[User].map { u =>
val is_uuid_valid = u.id.compareTo(UUID.fromString("d85ec250-bb5c-11ea-b3de-0242ac130030")) == 0
expect(is_uuid_valid) && expect(u.gender == "F")
}
case None => expect(false)
}
并想避免 for
之后的 flatMap
。如何将代码块从 flatMap
移动到 for
?
您可以使用 match
表达式:
for {
_ <- LiveUserQuery.make(DbManager.failRollback).create(user)
- <- IO.sleep(2.seconds)
a <- router.run(Request(GET, uri"/user/d85ec250-bb5c-11ea-b3de-0242ac130030")).value
result <- a match {
case Some(req) =>
req.as[User].map { u =>
val is_uuid_valid = u.id.compareTo(UUID.fromString("d85ec250-bb5c-11ea-b3de-0242ac130030")) == 0
expect(is_uuid_valid) && expect(u.gender == "F")
}
case None => expect(false)
}
} yield result
类似于 Matthias,但使用 fold
代替。
for {
_ <- LiveUserQuery.make(DbManager.failRollback).create(user)
- <- IO.sleep(2.seconds)
a <- router.run(Request(GET, uri"/user/d85ec250-bb5c-11ea-b3de-0242ac130030")).value
result <- a.fold(ifEmpty = expect(false)) { req =>
req.as[User].map { u =>
val is_uuid_valid = u.id.compareTo(UUID.fromString("d85ec250-bb5c-11ea-b3de-0242ac130030")) == 0
expect(is_uuid_valid) && expect(u.gender == "F")
}
}
} yield result
尝试OptionT
(for {
_ <- OptionT.liftF(LiveUserQuery.make(DbManager.failRollback).create(user))
_ <- OptionT.liftF(IO.sleep(2.seconds))
a <- OptionT(router.run(Request(GET, uri"/user/d85ec250-bb5c-11ea-b3de-0242ac130030")).value)
u <- OptionT.liftF(a.as[User])
is_uuid_valid = u.id.compareTo(UUID.fromString("d85ec250-bb5c-11ea-b3de-0242ac130030")) == 0
res <- OptionT.liftF(expect(is_uuid_valid) && expect(u.gender == "F"))
} yield res).getOrElseF(expect(false))
另一种方法,使用额外的 for/yield:
for {
_ <- LiveUserQuery.make(DbManager.failRollback).create(user)
_ <- IO.sleep(2.seconds)
a <- router.run(Request(GET, uri"/user/d85ec250-bb5c-11ea-b3de-0242ac130030")).value
res = (for {
req <- a
u <- req.as[User]
is_uuid_valid = u.id.compareTo(UUID.fromString("d85ec250-bb5c-11ea-b3de-0242ac130030")) == 0
} yield (expect(is_uuid_valid) && expect(u.gender == "F"))).getOrElse(expect(false))
} yield res
我有以下代码片段:
(for {
_ <- LiveUserQuery.make(DbManager.failRollback).create(user)
- <- IO.sleep(2.seconds)
a <- router.run(Request(GET, uri"/user/d85ec250-bb5c-11ea-b3de-0242ac130030")).value
} yield a).flatMap {
case Some(req) =>
req.as[User].map { u =>
val is_uuid_valid = u.id.compareTo(UUID.fromString("d85ec250-bb5c-11ea-b3de-0242ac130030")) == 0
expect(is_uuid_valid) && expect(u.gender == "F")
}
case None => expect(false)
}
并想避免 for
之后的 flatMap
。如何将代码块从 flatMap
移动到 for
?
您可以使用 match
表达式:
for {
_ <- LiveUserQuery.make(DbManager.failRollback).create(user)
- <- IO.sleep(2.seconds)
a <- router.run(Request(GET, uri"/user/d85ec250-bb5c-11ea-b3de-0242ac130030")).value
result <- a match {
case Some(req) =>
req.as[User].map { u =>
val is_uuid_valid = u.id.compareTo(UUID.fromString("d85ec250-bb5c-11ea-b3de-0242ac130030")) == 0
expect(is_uuid_valid) && expect(u.gender == "F")
}
case None => expect(false)
}
} yield result
类似于 Matthias,但使用 fold
代替。
for {
_ <- LiveUserQuery.make(DbManager.failRollback).create(user)
- <- IO.sleep(2.seconds)
a <- router.run(Request(GET, uri"/user/d85ec250-bb5c-11ea-b3de-0242ac130030")).value
result <- a.fold(ifEmpty = expect(false)) { req =>
req.as[User].map { u =>
val is_uuid_valid = u.id.compareTo(UUID.fromString("d85ec250-bb5c-11ea-b3de-0242ac130030")) == 0
expect(is_uuid_valid) && expect(u.gender == "F")
}
}
} yield result
尝试OptionT
(for {
_ <- OptionT.liftF(LiveUserQuery.make(DbManager.failRollback).create(user))
_ <- OptionT.liftF(IO.sleep(2.seconds))
a <- OptionT(router.run(Request(GET, uri"/user/d85ec250-bb5c-11ea-b3de-0242ac130030")).value)
u <- OptionT.liftF(a.as[User])
is_uuid_valid = u.id.compareTo(UUID.fromString("d85ec250-bb5c-11ea-b3de-0242ac130030")) == 0
res <- OptionT.liftF(expect(is_uuid_valid) && expect(u.gender == "F"))
} yield res).getOrElseF(expect(false))
另一种方法,使用额外的 for/yield:
for {
_ <- LiveUserQuery.make(DbManager.failRollback).create(user)
_ <- IO.sleep(2.seconds)
a <- router.run(Request(GET, uri"/user/d85ec250-bb5c-11ea-b3de-0242ac130030")).value
res = (for {
req <- a
u <- req.as[User]
is_uuid_valid = u.id.compareTo(UUID.fromString("d85ec250-bb5c-11ea-b3de-0242ac130030")) == 0
} yield (expect(is_uuid_valid) && expect(u.gender == "F"))).getOrElse(expect(false))
} yield res