从高阶函数构建通用的可重用迭代模块 [英] Build generic reusable iteration module from higher order function

查看:98
本文介绍了从高阶函数构建通用的可重用迭代模块的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何为迭代创建可重用的模块,从而使我能够:

How can I create a reusable module for iteration which allows me to:

  • 选择是否并行迭代
  • 让我指定需要执行的任务的高级功能

这里有一些虚拟功能.它们本身构成了问题的第二部分: 我是否应该在这里有一个接口,使这些功能中的每一个至少实现参数inputDay:String? 还是具有带有配置类的泛型函数更好,该配置类在其中实现了最小的接口?

Here are some dummy functions. They for itself pose the second part of the question: Should I have an interface here that each of these functions at least implements the parameter inputDay:String? or is it better to have a generic function with a configuration class, where the configuration implements a minimal interface?

def doStuff(inputDay: String, inputConfigSomething: String): Unit = println(inputDay + inputConfigSomething)
def doOtherStuff(inputDay: String): Unit = println(inputDay)

下面是迭代模块的一个示例,其中具体说明了所执行任务的具体实现:

Below an example of the iteration module first with a specific concrete iplementation of the task which is performed:

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)

现在,第二,代替具体的实现,应该可以传递一个高阶函数来控制所计算的内容. 不幸的是,下面的代码尚未编译.

Now, secondly, instead of concrete implementation a higher-order function should be passable to control what is computed. The code below unfortunately does not yet compile.

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.另外,一次又一次键入一些C和F也很烦人.

Trying again with a more generic implementation. this seems to be too convoluted. There must be a simpler way. Also, it still fails to compile as I cannot dynamically instantiate C in the iteration module. Also, it is fairly annoying to type some of the Cs and Fs again and again.

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"))

编辑

看到第一个答案之后.确实,这要简单得多.因此已经向前迈出了一大步. 但是,我需要能够将迭代项作为参数传递给函数

edit

After seeing the first answer. Indeed, this is much simpler. So already a great step forward. However, I need to be able to pass the iterated item into the function as a parameter

    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.如何访问当前迭代的项目并将其传递给函数?

will obviously not compile as d_each_reference is not defined there. How can I access the current iterated item and pass it to my function instead?

此外,尝试传递迭代项目和配置的扁平视图:

Also, trying to pass a flattened view of the iteration items and the configuration:

val configForIteration = days.map(d=> (d, something))
iterationModule[(String, String)](configForIteration, doStuff)

无法编译.

推荐答案

这是否更接近您的需求?

Does this get a little closer to what you're after?

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

这篇关于从高阶函数构建通用的可重用迭代模块的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆