【发布时间】:2019-07-08 02:20:30
【问题描述】:
我正在尝试定义一组“LazyChains”,用于在未来处理传入的消息。我希望 LazyChains 的 API 与 Scala 集合 API(即:Seq、Stream 等)无法区分。这将允许我在消息到达之前提前声明性地定义过滤/转换/操作。这可能是一个众所周知的模式,我不知道它的名字,所以这让我很难找到任何结果。
这是我想要完成的一个例子:
val chainA = LazyChain()
.filter(_ > 1)
.map(x => x * 2)
.foreach(println _)
val chainB = LazyChain()
.filter(_ > 5)
.flatMap(x => Seq(x, x))
.foreach(println _)
chainA.apply(2) // should print "4"
chainA.apply(1) // should print nothing
chainB.apply(10) // should print "10" - twice
Scala 集合 API 中是否已经存在这种模式?如果没有,我该如何实现这个类LazyChain?
这是我目前的尝试。我似乎无法弄清楚如何让这些类型工作:
case class LazyChain[I, O](val filter : Option[I => Boolean],
val transform : I => O,
val action : Option[O => Unit]) {
def filter(otherFilter : I => Boolean): LazyChain[I, O] = {
val newFilter = Some({ x : I => {
filter.map(_.apply(x)).getOrElse(true) && otherFilter.apply(x)
}})
copy(filter = newFilter)
}
def map[X](otherTransform : O => X) : LazyChain[I, X] = {
new LazyChain[I, X](
filter = filter,
transform = (x: I) => {
otherTransform.apply(transform.apply(x))
},
/*
type mismatch;
[error] found : Option[O => Unit]
[error] required: Option[X => Unit]
*/
action = action
)
}
def flatMap[X](otherTransform : O => Seq[X]) : LazyChain[I, X] = {
new LazyChain[I, X](
filter = filter,
transform = (x: I) => {
/**
type mismatch;
[error] found : Seq[X]
[error] required: X
*/
otherTransform.apply(transform.apply(x))
}
)
}
def foreach(newAction : O => Unit) = {
copy(action = Some(newAction))
}
def apply(element : I) = {
if (filter.map(_.apply(element)).getOrElse(true)) {
val postTransform = transform.apply(element)
action.foreach(_.apply(postTransform))
}
}
}
object LazyChain {
def apply[X]() : LazyChain[X, X] = {
new LazyChain(filter = None, transform = x => x, action = None)
}
}
【问题讨论】:
-
Scala 有Views 可以转换惰性集合中的任何集合。也许那里有一些有用的提示
-
akka-streams将允许您执行此操作。但这对你来说可能太“重”了 -
Iteratees 让你很自然地做这样的事情:你可以建立转换(enumeratees)并将它们插入源(enumerators)和接收器(iteratees),而这些都只是值。
-
(完全披露:我维护an iteratee library for Scala。)
-
感谢这些建议。我会看看这三个。我主要对我可以自己实现的轻量级解决方案感兴趣(也是我自己的知识)。我相信我会通过查看这些库的实现来学习。