scala - Scala 中的嵌套过滤器要么在 Future[Try[Int]] 之上
问题描述
我是 scala 的初学者,我正在尝试在Either
. 现在我有一个getTaskId
返回的函数,Future[Try[Int]]
我的函数filter logic
就是基于它Int
。现在由于filter
期望boolean
,我无法在下面的代码片段中返回相同的内容。
val records: List[CommittableRecord[Either[Throwable, MyEvent]]] = ???
records.filter {
(x: CommittableRecord[Either[Throwable,MyEvent]]) =>
x.value match {
case Right(event: MyEvent) =>
getTaskId(event.get("task").get) filter {
case Success(value) => value > 1
case Failure(exception) => false
}
case Left(_) => false
}
}
我收到返回的filter
on 函数的错误getTaskId
Future[Try[Int]]
type mismatch;
found : scala.concurrent.Future[scala.util.Try[Int]]
required: Boolean
所以基本上filter
除了Future
返回另一个Future
但父母filter
期待一个boolean
任何帮助是极大的赞赏。
解决方案
您在这里遇到了 scala 中的两个困难功能:
- 大量的语法糖
- scala 中的最佳实践不是
Future
在你内部等待一些业务逻辑的结果,使用:Await.result(future, timeout)
。你应该只在宇宙的尽头使用它(在大多数情况下:在你的程序结束时)。
所以,我建议重构你当前的逻辑,从过滤List[CommittableRecord]
结果中使结果是非阻塞的 -Future[List[CommittableRecord]]
使用过滤的记录列表。您可以使用这个未来,就像它只是另一个数据容器(如Option[T]
)并在程序结束时调用阻塞操作,如Await.result
.
代码示例:
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future.sequence
import scala.util.{Failure, Success, Try}
case class Task()
type MyEvent = Map[String, Task]
case class CommittableRecord(value: Either[Throwable, MyEvent])
def getTaskId(task: Task): Future[Try[Int]] = ???
val records: List[CommittableRecord] = List.empty[CommittableRecord]
val result: Future[List[CommittableRecord]] = sequence(
records.map(
x =>
(x.value match {
case Left(_) => Future(false)
case Right(value) =>
getTaskId(value.get("task").get)
.map {
case Failure(_) => false
case Success(id) => id > 1
}
}).map(_ -> x)
)
).map(
idMoreThen1AndRecordList =>
idMoreThen1AndRecordList.collect {
case (true, record) => record
}
)
或者,经过一些重构并将 lambda 表达式替换为函数:
def isTaskIdMoreThenOneAndRecord(record: CommittableRecord): Future[(Boolean, CommittableRecord)] =
(record.value match {
case Left(_) => Future(false)
case Right(value) =>
getTaskId(value.get("task").get)
.map(tryId => tryId.fold(_ => false, _ > 1))
}).map(_ -> record)
def filterRecordsWithTaskIdMoreThenOne(
isMoreOneAndRecordList: List[(Boolean, CommittableRecord)]
): List[CommittableRecord] =
isMoreOneAndRecordList.collect {
case (true, record) => record
}
val result: Future[List[CommittableRecord]] =
sequence(records.map(isTaskIdMoreThenOneAndRecord))
.map(filterRecordsWithTaskIdMoreThenOne)
因此,您将拥有Future[List[CommittableRecord]]
并且可以使用map
以下函数处理过滤后的记录:
result.map((filteredRecords: List[CommittableRecord]) => \*do something with filtered records*\)
或者您可以使用flatMap
.
有用的链接:
- 在scala 文档上阅读更多关于 Future 的信息
- 关于 lambda 表达式的文章
- scala并发的一些最佳实践
推荐阅读
- jquery - Jquery Tooltipster - ajax 后访问 DOM
- oracle - 通过 azure databricks 运行 oracle 查询
- woocommerce - Woocommerce - 在管理面板中显示订单总量
- android - 为什么 dlopen() 会在两个不同的调用中为同一个共享库返回两个不同的句柄?
- python - 将创建日期戳添加到 seaborn 可视化
- java - 瞬态变量的约束验证异常
- laravel - localhost 无法加载应用程序 centos 服务器
- flutter - 键盘在较旧的 Android 版本上退出全屏模式
- python - Python中的多项式回归曲线
- acumatica - 导入方案是否使用 DAC 中指定的 PXDefault 属性?