software - scala tutorial
¿Hay una breve sintaxis para ejecutar un bloque n veces en Scala? (5)
Me encuentro escribiendo código como este cuando quiero repetir algunas ejecuciones n veces:
for (i <- 1 to n) { doSomething() }
Estoy buscando una sintaxis más corta como esta:
n.times(doSomething())
¿Algo como esto existe en Scala ya?
EDITAR
Pensé en usar el método foreach () de Range, pero luego el bloque necesita tomar un parámetro que nunca usa.
(1 to n).foreach(ignored => doSomething())
Con scalaz 5 :
doSomething.replicateM[List](n)
Con scalaz 6 :
n times doSomething
Y eso funciona como se esperaría con la mayoría de los tipos (más precisamente, para cada monoide ):
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!
También podría decir doSomething replicateM_ 5
que solo funciona si doSomething
es un valor idiomático (ver Applicative
). Tiene una seguridad de tipo mejor, ya que puedes hacer esto:
scala> putStrLn("Foo") replicateM_ 5
res6: scalaz.effects.IO[Unit] = scalaz.effects.IO$$anon$2@8fe8ee7
pero no esto:
scala> { System.exit(0) } replicateM_ 5
<console>:15: error: value replicateM_ is not a member of Unit
Déjame ver que lo saques en Ruby.
La clase Range tiene un método foreach que creo que es justo lo que necesita. Por ejemplo, esto:
0.to(5).foreach(println(_))
producido
0
1
2
3
4
5
No estoy al tanto de nada en la biblioteca. Puede definir una conversión y clase implícita de utilidad que puede importar según sea necesario.
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 acaba de publicar una respuesta similar mientras escribía esto ...
Podrías definir fácilmente uno usando el patrón 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
Puede ser tan simple como esto:
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