Есть ли короткий синтаксис для выполнения блока n раз в Scala?

Я нахожу, что пишу такой код, когда хочу повторить некоторое выполнение n раз:

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

Я ищу более короткий синтаксис, например:

n.times(doSomething())

Что-то вроде этого уже существует в Scala?

ИЗМЕНИТЬ

Я думал об использовании метода Range foreach(), но тогда блок должен принять параметр, который он никогда не использует.

(1 to n).foreach(ignored => doSomething())

Ответы

Ответ 1

Вы можете легко определить один, используя шаблон Pimp My Library.

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

Ответ 2

Класс Range имеет для него метод foreach, который, я думаю, является именно тем, что вам нужно. Например, это:

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

произведено

0
1
2
3
4
5

Ответ 3

С scalaz 5:

doSomething.replicateM[List](n)

С scalaz 6:

n times doSomething

И это работает так, как вы ожидали бы с большинством типов (точнее, для каждого моноида):

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] = [email protected]

scala> res5.unsafePerformIO
Hello, World!
Hello, World!
Hello, World!
Hello, World!
Hello, World!

Вы также можете сказать doSomething replicateM_ 5, который работает только в том случае, если ваш doSomething является идиоматическим значением (см. Applicative). Он имеет более безопасный тип безопасности, поскольку вы можете это сделать:

scala> putStrLn("Foo") replicateM_ 5
res6: scalaz.effects.IO[Unit] = [email protected]

но не это:

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

Позвольте мне видеть, как вы это делаете в Ruby.

Ответ 4

Я ничего не знаю в библиотеке. Вы можете определить неявное преобразование и класс, которые вы можете импортировать по мере необходимости.

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"))

Рахул только что опубликовал аналогичный ответ, пока я писал это...

Ответ 5

Это может быть так просто:

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