Is there a brief syntax for executing a block n times in Scala?

前端 未结 6 1545
误落风尘
误落风尘 2020-12-13 05:54

I find myself writing code like this when I want to repeat some execution n times:

for (i <- 1 to n) { doSomething() }

I\'m looking for

相关标签:
6条回答
  • 2020-12-13 06:13

    It can be as simple as this:

    scala> def times(n:Int)( code: => Unit ) {
              for (i <- 1 to n) code
           }
    times: (n: Int)(code: => Unit)Unit
    
    scala> times(5) {println("here")}
    here
    here
    here
    here
    here
    
    0 讨论(0)
  • 2020-12-13 06:16

    With scalaz 5:

    doSomething.replicateM[List](n)
    

    With scalaz 6:

    n times doSomething
    

    And that works as you would expect with most types (more precisely, for every monoid):

    scala> import scalaz._; import Scalaz._; import effects._;
    import scalaz._
    import Scalaz._
    import effects._
    
    scala> 5 times "foo"
    res0: java.lang.String = foofoofoofoofoo
    
    scala> 5 times List(1,2)
    res1: List[Int] = List(1, 2, 1, 2, 1, 2, 1, 2, 1, 2)
    
    scala> 5 times 10
    res2: Int = 50
    
    scala> 5 times ((x: Int) => x + 1).endo
    res3: scalaz.Endo[Int] = <function1>
    
    scala> res3(10)
    res4: Int = 15
    
    scala> 5 times putStrLn("Hello, World!")
    res5: scalaz.effects.IO[Unit] = scalaz.effects.IO$$anon$2@36659c23
    
    scala> res5.unsafePerformIO
    Hello, World!
    Hello, World!
    Hello, World!
    Hello, World!
    Hello, World!
    

    You could also say doSomething replicateM_ 5 which only works if your doSomething is an idiomatic value (see Applicative). It has better type-safety, since you can do this:

    scala> putStrLn("Foo") replicateM_ 5
    res6: scalaz.effects.IO[Unit] = scalaz.effects.IO$$anon$2@8fe8ee7
    

    but not this:

    scala> { System.exit(0) } replicateM_ 5
    <console>:15: error: value replicateM_ is not a member of Unit
    

    Let me see you pull that off in Ruby.

    0 讨论(0)
  • 2020-12-13 06:20

    The Range class has a foreach method on it that I think is just what you need. For example, this:

     0.to(5).foreach(println(_))
    

    produced

    0
    1
    2
    3
    4
    5

    0 讨论(0)
  • 2020-12-13 06:25
    def times(f: => Unit)(cnt:Int) :Unit = {
      List.fill(cnt){f}
    }
    
    0 讨论(0)
  • 2020-12-13 06:31

    I'm not aware of anything in the library. You can define a utility implicit conversion and class that you can import as needed.

    class TimesRepeat(n:Int) {
      def timesRepeat(block: => Unit): Unit = (1 to n) foreach { i => block }
    }
    object TimesRepeat {
      implicit def toTimesRepeat(n:Int) = new TimesRepeat(n)
    }
    
    import TimesRepeat._
    
    3.timesRepeat(println("foo"))
    

    Rahul just posted a similar answer while I was writing this...

    0 讨论(0)
  • 2020-12-13 06:38

    You could easily define one using Pimp My Library pattern.

    scala> implicit def intWithTimes(n: Int) = new {        
         |   def times(f: => Unit) = 1 to n foreach {_ => f}
         | }
    intWithTimes: (n: Int)java.lang.Object{def times(f: => Unit): Unit}
    
    scala> 5 times {
         |   println("Hello World")
         | }
    Hello World
    Hello World
    Hello World
    Hello World
    Hello World
    
    0 讨论(0)
提交回复
热议问题