如何在 Scala 中调用一个方法 n 次?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7530194/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to call a method n times in Scala?
提问by Jonas
I have a case where I want to call a method n times, where n is an Int. Is there a good way to do this in a "functional" way in Scala?
我有一个案例,我想调用一个方法 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
}
}
I think a closure is a good solution for this, but I can't get it working. I have also tried with a for-loop, but it's not a beautiful functional solution.
我认为闭包是一个很好的解决方案,但我无法让它工作。我也尝试过 for 循环,但这不是一个漂亮的功能解决方案。
采纳答案by Travis Brown
A more functional solution would be to use a fold with an immutable queue and Queue's filland dropmethods:
一个功能更强大的解决方案将是使用一个倍的不可变队列和Queue的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)
}
}
Or even better, capture your "supply"/"sale"distinction in subclasses of Eventand avoid the awkward Option[BigDecimal]business:
或者更好的是,在子类中捕获您的"supply"/"sale"区别Event并避免尴尬的Option[BigDecimal]业务:
sealed trait Event { def quantity: Int }
case class Supply(quantity: Int, value: BigDecimal) extends Event
case class Sale(quantity: Int) extends Event
val lst = List(
Supply(3, BigDecimal("39.00")),
Sale(1),
Supply(1, BigDecimal("41.00"))
)
val queue = lst.foldLeft(Queue.empty[BigDecimal]) { (q, e) => e match {
case Sale(quantity) => q.drop(quantity)
case Supply(quantity, value) => q ++ Queue.fill(quantity)(value)
}}
This doesn't directly answer your question (how to call a function a specified number of times), but it's definitely more idiomatic.
这并没有直接回答您的问题(如何以指定次数调用函数),但它绝对更惯用。
回答by tenshi
The simplest solution is to use range, I think:
最简单的解决方案是使用范围,我认为:
(1 to n) foreach (x => /* do something */)
But you can also create this small helper function:
但是你也可以创建这个小辅助函数:
implicit def intTimes(i: Int) = new {
def times(fn: => Unit) = (1 to i) foreach (x => fn)
}
10 times println("hello")
this code will print "hello" 10 times. Implicit conversion intTimesmakes method timesavailable on all ints. So in your case it should look like this:
此代码将打印“你好”10 次。隐式转换intTimes使方法times可用于所有整数。所以在你的情况下它应该是这样的:
event.quantity times queue.enqueue(event.value)
event.quantity times queue.dequeue()
回答by oxbow_lakes
Not quite an answer to your question, but if you had an endomorphism (i.e. a transformation A => A), then using scalazyou could use the natural monoid for Endo[A]
不是你问题的答案,但如果你有一个内同态(即转换A => A),那么使用scalaz你可以使用自然幺半群Endo[A]
N times func apply target
So that:
以便:
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
回答by Luigi Plinge
import List._
fill(10) { println("hello") }
Simple, built-in, and you get a List of Units as a souvenier!
简单,内置,你会得到一个单位列表作为纪念品!
But you'll never need to call a function multiple times if you're programming functionally.
但是,如果您进行函数式编程,则永远不需要多次调用一个函数。
回答by Alexey Romanov
With recursion:
递归:
def repeat(n: Int)(f: => Unit) {
if (n > 0) {
f
repeat(n-1)(f)
}
}
repeat(event.quantity) { queue.enqueue(event.value) }

