我有一个案例,我想调用一个方法n次,其中n是一个Int。在Scala中有一种以“功能”方式执行此操作的好方法吗?
case class Event(name: String, quantity: Int, value: Option[BigDecimal])
// a list of events
val lst = List(
Event("supply", 3, Some(new java.math.BigDecimal("39.00"))),
Event("sale", 1, None),
Event("supply", 1, Some(new java.math.BigDecimal("41.00")))
)
// a mutable queue
val queue = new scala.collection.mutable.Queue[BigDecimal]
lst.map { event =>
event.name match {
case "supply" => // call queue.enqueue(event.value) event.quantity times
case "sale" => // call queue.dequeue() event.quantity times
}
}
我认为关闭是一个很好的解决方案,但我不能让它工作。我也尝试过for-loop,但它不是一个漂亮的功能解决方案。
答案 0 :(得分:35)
最简单的解决方案是使用范围,我认为:
(1 to n) foreach (x => /* do something */)
但你也可以创建这个小辅助函数:
implicit def intTimes(i: Int) = new {
def times(fn: => Unit) = (1 to i) foreach (x => fn)
}
10 times println("hello")
此代码将打印“hello”10次。隐式转化intTimes
使方法times
可用于所有整数。所以在你的情况下它应该是这样的:
event.quantity times queue.enqueue(event.value)
event.quantity times queue.dequeue()
答案 1 :(得分:12)
对你的问题不是一个完全答案,但如果你有一个内同态(即转换A => A
),那么使用scalaz你可以使用自然的monoid来Endo[A]
N times func apply target
那样:
scala> import scalaz._; import Scalaz._
import scalaz._
import Scalaz._
scala> Endo((_:Int) * 2).multiply(5)
res3: scalaz.Endo[Int] = Endo(<function1>)
scala> res1(3)
res4: Int = 96
答案 2 :(得分:10)
更实用的解决方案是使用具有不可变队列的折叠和Queue
的{{1}}和fill
方法:
drop
甚至更好,在 val queue = lst.foldLeft(Queue.empty[Option[BigDecimal]]) { (q, e) =>
e.name match {
case "supply" => q ++ Queue.fill(e.quantity)(e.value)
case "sale" => q.drop(e.quantity)
}
}
的子类中捕获"supply"
/ "sale"
区别,避免尴尬的Event
业务:
Option[BigDecimal]
这并没有直接回答你的问题(如何调用一个指定次数的函数),但它绝对是更惯用的。
答案 3 :(得分:8)
import List._
fill(10) { println("hello") }
简单,内置,你得到一个单位列表作为纪念品!
但如果您正在进行功能编程,则永远不需要多次调用函数。
答案 4 :(得分:4)
使用递归:
def repeat(n: Int)(f: => Unit) {
if (n > 0) {
f
repeat(n-1)(f)
}
}
repeat(event.quantity) { queue.enqueue(event.value) }