将高阶函数包装到进度条中

Wrap higher order function into progress bar

我有一个可以应用任意函数的迭代模块 (),并且很想将它包装到进度条中。

val things = Range(1,10)
def iterationModule[A](
                        iterationItems: Seq[A],
                        functionToApply: A => Any
                      ): Unit = {
    iterationItems.foreach(functionToApply)
}

def foo(s:Int) = println(s)

iterationModule[Int](things, foo)

基本的 progressbar 可能如下所示:

import me.tongfei.progressbar.ProgressBar
val pb = new ProgressBar("Test", things.size)
things.foreach(t=> {
  println(t)
  pb.step
})

但是传递给迭代器模块的函数如何被拦截并用progressbar包围,即调用pb.step

一个烦人的可能性是将可变 pb 对象传递给每个函数(让它实现一个接口)。 但是是否也可以拦截并包围这个步进逻辑正在传递的函数? 但是,当使用 Seq().par.foreach 循环时,这可能会出现问题。

我需要代码在 Scala 2.11 中工作。

编辑

一个更复杂的例子:

val things = Range(1,100).map(_.toString)

def iterationModule[A](
                        iterationItems: Seq[A],
                        functionToApply: A => Any,
                        parallel: Boolean = false
                      ): Unit = {
  val pb = new ProgressBar(functionToApply.toString(), iterationItems.size)
  if (parallel) {
    iterationItems.par.foreach(functionToApply)
  } else {
    iterationItems.foreach(functionToApply)
  }
}

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

iterationModule[String](things, doStuff(_, "foo"))

该函数应该能够接受迭代项和附加参数。

编辑 2

import me.tongfei.progressbar.ProgressBar

val things = Range(1,100).map(_.toString)

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

def iterationModulePb[A](items: Seq[A], f: A => Any, parallel: Boolean = false): Unit = {
  val pb = new ProgressBar(f.toString, items.size)
  val it = if (parallel) {
    items.par.iterator
  } else {
    items.iterator
  }
  it.foreach { x =>
    f(x)
    pb.step()
  }
}
iterationModulePb[String](things, doStuff(_, "foo"))

经过一些讨论后,我弄清楚了如何将 Seq 与标准迭代器一起使用。

对于 Scala 2.13 这将是最通用的形式。

import me.tongfei.progressbar.ProgressBar

def iterationModule[A](items: IterableOnce[A], f: A => Any): Unit = {
  val (it, pb) =
    if (items.knowSize != -1)
      items.iterator -> new ProgressBar("Test", items.knowSize)
    else {
      val (iter1, iter2) = items.iterator.split
      iter1 -> new ProgressBar("Test", iter2.size)
    }

  it.foreach { x =>
    f(x)
    pb.step()
  }
}

注意:大部分更改只是为了使代码更通用,但总体思路只是创建一个函数,将原始函数和对 [=23= 的调用都包装起来]进度条.


编辑

2.11

的简化解决方案
def iterationModule[A](items: Seq[A], parallel: Boolean = false)
                      (f: A => Any): Unit = {
  val pb = new ProgressBar("test", items.size)

  val it = if (parallel) {
    items.iterator.par
  } else {
    items.iterator
  }

  it.foreach { a =>
    f(a)
    pb.step()
  }
}