Существует ли краткий синтаксис для выполнения блока n раз в Scala? - PullRequest
48 голосов
/ 16 мая 2010

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

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

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

n.times(doSomething())

Что-то подобное уже существует в Scala?

EDIT

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

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

Ответы [ 5 ]

49 голосов
/ 16 мая 2010

Вы можете легко определить один, используя шаблон 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
34 голосов
/ 16 мая 2010

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

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

произведено

0
1
2
3 * * +1010 4
5

21 голосов
/ 31 марта 2011

С Скалаз 5 :

doSomething.replicateM[List](n)

С скалаз 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] = scalaz.effects.IO$$anon$2@36659c23

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] = scalaz.effects.IO$$anon$2@8fe8ee7

но не это:

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

Позвольте мне увидеть, как вы справляетесь с этим в Ruby.

5 голосов
/ 16 мая 2010

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

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

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

2 голосов
/ 31 марта 2011

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

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...