现在我在scala 2.11.7中创建了CUI进度条对象,我正在模仿在F#,Console.showProgress中找到的那个,我发现它非常好。我尝试制作的进度条可以像:
一样使用pregressBar ((1 to 100)) { i =>
doSomeWork(i)
}
看起来像:
67% [================================> ]
我希望这个progressBar对象基于第一个参数序列做一些工作,并返回包含该工作结果的序列(这与map函数非常相似)。 而且我希望它像map函数一样,它输出的容器类需要与其输入的容器类相同。所以当输入是List时,输出也是List,当Array,输出是Array时.. 但就目前而言,我的实现只接受List类,即使我正在尝试使用CanBuildFrom。 这是代码:
import scala.collection.generic.CanBuildFrom
import scala.collection.mutable.Builder
import scala.language.higherKinds
object progressBar {
def apply[A, B, S[A] <: Seq[A]](seq: S[A])(f: A => B)
(implicit bf: CanBuildFrom[S[A], B, S[B]]): S[B] = {
val result =
for {i <- 0 until seq.size
r = ((i.toDouble) / (seq.size.toDouble) * 100).toInt + 1
_ = printf("%3d%% [%-50s]\r",r,"="*(r/2-1)+">")
_ = System.out.flush
v = f(seq(i))
} yield v
println
result.to[S]
}
def main(args: Array[String]): Unit = {
// test
progressBar(List(1,2,3)) {_ =>
Thread sleep 100
0
}
}
}
例如,当我在主要部分中将List(1,2,3)更改为Array时,只会抛出类型不匹配错误。如何解决这个问题按预期工作? 我提前谢谢你。
答案 0 :(得分:0)
由于"Expression: invalid null pointer"
不是Array
,因此类型推断还有额外的工作要做。
一种解决方案是Seq
的重载:
Array
此外,
import scala.collection.generic.CanBuildFrom
import scala.collection.mutable.Builder
import scala.language.higherKinds
import collection.mutable.WrappedArray
import reflect.ClassTag
object progressBar {
def apply[A, B, S[A] <: Seq[A]](seq: S[A])(f: A => B)
(implicit bf: CanBuildFrom[S[A], B, S[B]]): S[B] = {
val result = seq.zipWithIndex map { case (v, i) =>
val r = ((i.toDouble) / (seq.size.toDouble) * 100).toInt + 1
printf("%3d%% [%-50s]\r",r,"="*(r/2-1)+">")
System.out.flush
f(v)
}
println
result.to[S]
}
def apply[A, B : ClassTag](xs: Array[A])(f: A => B): Array[B] = {
val w = apply(WrappedArray.make[A](xs))(f)
w.array
}
}
object Test extends App {
// test
progressBar(List(1,2,3)) { _ =>
Thread sleep 1000
0
}
progressBar.apply(Array(1,2,3)) { _ =>
Thread sleep 1000
0
}
}
允许
object X {
implicit class Bar[A, C[A] <: Seq[A]](private val vs: C[A]) {
def progress[B](f: A => B)(implicit bf: CanBuildFrom[C[A], B, C[B]]): C[B] =
progressBar(vs)(f)(bf)
}
implicit class ArrayBar[A](private val vs: Array[A]) {
def progress[B: ClassTag](f: A => B): Array[B] =
(WrappedArray.make[A](vs) progress f).array
}
}