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

问题描述 投票:1回答:1

我有一个迭代模块,该模块可以应用任意函数(Build generic reusable iteration module from higher order function),希望将其包装到进度栏中。

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 generics iteration progress-bar higher-order-functions
1个回答
3
投票

对于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()
  }
}

注意:大多数更改只是为了使代码更通用,而总体思路只是创建一个包装原始函数和对[[ProgressBar的调用的函数。


编辑

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() } }

© www.soinside.com 2019 - 2024. All rights reserved.