从高阶函数构建通用的可重用迭代模块

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