从高阶函数构建通用的可重用迭代模块
Build generic reusable iteration module from higher order function
我如何创建一个可重用的迭代模块,它允许我:
- 选择是否并行迭代
- 让我指定一个需要执行任务的高阶函数
这里有一些虚拟函数。他们自己提出了问题的第二部分:
我应该在这里有一个接口,让这些函数中的每一个至少实现参数inputDay:String
吗?
还是拥有配置 class 的通用函数更好,其中配置实现最小接口?
def doStuff(inputDay: String, inputConfigSomething: String): Unit = println(inputDay + inputConfigSomething)
def doOtherStuff(inputDay: String): Unit = println(inputDay)
下面是迭代模块的示例,首先是执行任务的具体具体实现:
val days = Seq("20190101", "20190102", "20190103")
val something = "foo"
def iteration(d: Seq[String], parallel: Boolean = false) = {
if (parallel) {
d.par.foreach(dd => {
println(dd)
})
} else {
d.foreach(dd => {
println(dd)
})
}
}
iteration(days)
现在,其次,应该可以通过高阶函数来控制计算的内容,而不是具体的实现。
不幸的是,下面的代码还没有编译。
def iterationModule(d: Seq[String], functionToApply: Function, parallel: Boolean = false) = {
if (parallel) {
d.par.foreach(dd => {
functionToApply(dd)
})
} else {
d.foreach(dd => {
functionToApply(dd)
})
}
}
iterationModule(days, doStuff)
再次尝试使用更通用的实现。这似乎太复杂了。必须有更简单的方法。还,
它仍然无法编译,因为我无法在迭代模块中动态实例化 C。另外,一遍又一遍地输入一些 Cs 和 Fs 是相当烦人的。
trait MinimalIterationParameters {
def inputDay: String
}
trait FunctionParameters
trait OperationService[C <: MinimalIterationParameters, F <: FunctionParameters] {
def doOperation(config: C, functionParameter: F): Unit
}
case class Minimal(override val inputDay: String) extends MinimalIterationParameters
case class ExtendedThing(inputConfigSomething: String) extends FunctionParameters
object MyDummyOperationService extends OperationService[Minimal, ExtendedThing] {
override def doOperation(config: Minimal, functionParameter: ExtendedThing): Unit = {
println(config.inputDay + functionParameter.inputConfigSomething)
}
}
def iterationModuleGeneric[C <: MinimalIterationParameters, F <: FunctionParameters](d: Seq[String], functionToApply: OperationService[C, F], f: F, parallel: Boolean = false) = {
if (parallel) {
d.par.foreach(dd => {
functionToApply.doOperation(C(dd), f)
})
} else {
d.foreach(dd => {
functionToApply.doOperation(C(dd), f)
})
}
}
val c = Minimal
iterationModuleGeneric[Minimal, ExtendedThing](days, MyDummyOperationService, f = ExtendedThing("foo"))
编辑
看到第一个答案后。事实上,这要简单得多。所以已经向前迈出了一大步。
但是,我需要能够将迭代项作为参数传递给函数
def iterationModule[A](d: Seq[A], functionToApply: A => Any, parallel: Boolean = false): Unit =
if (parallel) {
d.par.foreach(functionToApply)
}
else {
d.foreach(functionToApply)
}
def doStuff(inputDay: String, inputConfigSomething: String): Unit = println(inputDay + inputConfigSomething)
iterationModule[String](days, doStuff(d_each_reference, "foo"))
但是:
iterationModule[String](days, doStuff(d_each_reference, "foo"))
显然不会编译,因为那里没有定义 d_each_reference
。我怎样才能访问当前的迭代项并将其传递给我的函数?
此外,尝试传递迭代项和配置的扁平化视图:
val configForIteration = days.map(d=> (d, something))
iterationModule[(String, String)](configForIteration, doStuff)
不会编译。
这是否更接近您所追求的目标?
def iterationModule[A](d: Seq[A], functionToApply: A=>Any, parallel: Boolean = false) :Unit =
if (parallel) d.par.foreach(functionToApply)
else d.foreach(functionToApply)
def doStuff(a:Char, b :String) :Unit = println(a+b)
iterationModule(List('X','Y','Z'), doStuff(_, "foo"))
//Xfoo
//Yfoo
//Zfoo
我如何创建一个可重用的迭代模块,它允许我:
- 选择是否并行迭代
- 让我指定一个需要执行任务的高阶函数
这里有一些虚拟函数。他们自己提出了问题的第二部分:
我应该在这里有一个接口,让这些函数中的每一个至少实现参数inputDay:String
吗?
还是拥有配置 class 的通用函数更好,其中配置实现最小接口?
def doStuff(inputDay: String, inputConfigSomething: String): Unit = println(inputDay + inputConfigSomething)
def doOtherStuff(inputDay: String): Unit = println(inputDay)
下面是迭代模块的示例,首先是执行任务的具体具体实现:
val days = Seq("20190101", "20190102", "20190103")
val something = "foo"
def iteration(d: Seq[String], parallel: Boolean = false) = {
if (parallel) {
d.par.foreach(dd => {
println(dd)
})
} else {
d.foreach(dd => {
println(dd)
})
}
}
iteration(days)
现在,其次,应该可以通过高阶函数来控制计算的内容,而不是具体的实现。 不幸的是,下面的代码还没有编译。
def iterationModule(d: Seq[String], functionToApply: Function, parallel: Boolean = false) = {
if (parallel) {
d.par.foreach(dd => {
functionToApply(dd)
})
} else {
d.foreach(dd => {
functionToApply(dd)
})
}
}
iterationModule(days, doStuff)
再次尝试使用更通用的实现。这似乎太复杂了。必须有更简单的方法。还, 它仍然无法编译,因为我无法在迭代模块中动态实例化 C。另外,一遍又一遍地输入一些 Cs 和 Fs 是相当烦人的。
trait MinimalIterationParameters {
def inputDay: String
}
trait FunctionParameters
trait OperationService[C <: MinimalIterationParameters, F <: FunctionParameters] {
def doOperation(config: C, functionParameter: F): Unit
}
case class Minimal(override val inputDay: String) extends MinimalIterationParameters
case class ExtendedThing(inputConfigSomething: String) extends FunctionParameters
object MyDummyOperationService extends OperationService[Minimal, ExtendedThing] {
override def doOperation(config: Minimal, functionParameter: ExtendedThing): Unit = {
println(config.inputDay + functionParameter.inputConfigSomething)
}
}
def iterationModuleGeneric[C <: MinimalIterationParameters, F <: FunctionParameters](d: Seq[String], functionToApply: OperationService[C, F], f: F, parallel: Boolean = false) = {
if (parallel) {
d.par.foreach(dd => {
functionToApply.doOperation(C(dd), f)
})
} else {
d.foreach(dd => {
functionToApply.doOperation(C(dd), f)
})
}
}
val c = Minimal
iterationModuleGeneric[Minimal, ExtendedThing](days, MyDummyOperationService, f = ExtendedThing("foo"))
编辑
看到第一个答案后。事实上,这要简单得多。所以已经向前迈出了一大步。 但是,我需要能够将迭代项作为参数传递给函数
def iterationModule[A](d: Seq[A], functionToApply: A => Any, parallel: Boolean = false): Unit =
if (parallel) {
d.par.foreach(functionToApply)
}
else {
d.foreach(functionToApply)
}
def doStuff(inputDay: String, inputConfigSomething: String): Unit = println(inputDay + inputConfigSomething)
iterationModule[String](days, doStuff(d_each_reference, "foo"))
但是:
iterationModule[String](days, doStuff(d_each_reference, "foo"))
显然不会编译,因为那里没有定义 d_each_reference
。我怎样才能访问当前的迭代项并将其传递给我的函数?
此外,尝试传递迭代项和配置的扁平化视图:
val configForIteration = days.map(d=> (d, something))
iterationModule[(String, String)](configForIteration, doStuff)
不会编译。
这是否更接近您所追求的目标?
def iterationModule[A](d: Seq[A], functionToApply: A=>Any, parallel: Boolean = false) :Unit =
if (parallel) d.par.foreach(functionToApply)
else d.foreach(functionToApply)
def doStuff(a:Char, b :String) :Unit = println(a+b)
iterationModule(List('X','Y','Z'), doStuff(_, "foo"))
//Xfoo
//Yfoo
//Zfoo