How to call a method n times in Scala?

后端 未结 5 1028
轮回少年
轮回少年 2021-02-18 23:04

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?

case class Event(name: S         


        
相关标签:
5条回答
  • 2021-02-18 23:28

    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 intTimes makes method times available on all ints. So in your case it should look like this:

    event.quantity times queue.enqueue(event.value) 
    event.quantity times queue.dequeue() 
    
    0 讨论(0)
  • 2021-02-18 23:43

    Not quite an answer to your question, but if you had an endomorphism (i.e. a transformation A => A), then using scalaz you could use the natural monoid for 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
    
    0 讨论(0)
  • 2021-02-18 23:47

    A more functional solution would be to use a fold with an immutable queue and Queue's fill and drop methods:

     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 Event and avoid the awkward Option[BigDecimal] business:

    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.

    0 讨论(0)
  • 2021-02-18 23:48
    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.

    0 讨论(0)
  • 2021-02-18 23:53

    With recursion:

    def repeat(n: Int)(f: => Unit) { 
      if (n > 0) {
        f
        repeat(n-1)(f)
      }
    }
    
    repeat(event.quantity) { queue.enqueue(event.value) }
    
    0 讨论(0)
提交回复
热议问题