2011-04-23 9 views
31

estoy buscando un equivalente de:más elegantes bucle de repetición en Scala

for(_ <- 1 to n) 
    some.code() 

que sería más corto y más elegante. ¿No hay en Scala algo similar a esto?

rep(n) 
    some.code() 

Esta es una de las construcciones más comunes después de todo.

PS

sé que es fácil de implementar representante, pero estoy buscando algo predefinido.

+1

Básicamente, lo que buscas es el equivalente a la de/end' '42.times no some_thing de Smalltalk Ruby, ¿derecho? Me refiero a "equivalente" no solo en el sentido de funcionalidad, sino también en "ligereza" sintáctica. –

+2

Elegante es un criterio subjetivo. – huynhjl

Respuesta

69
1 to n foreach { _ => some.code() } 
+0

¿Tiene esto alguna ventaja (rendimiento, estilo) en el camino mencionado en la pregunta? – benroth

+3

@benroth No. De hecho, 'for (_ <- 1 an) some.code()' está _translated_ en '1 to n foreach {_ => some.code()}' durante la compilación. –

+1

No estoy convencido de que sea elegante. ¿El constructor de 1 a n no crea una secuencia antes de que se llame al foreach? ¿Cuál es la sobrecarga de memoria si n = 65000? – Willem

8

Yo sugeriría algo como esto:

List.fill(10)(println("hi")) 

hay otras maneras, por ejemplo .:

(1 to 10).foreach(_ => println("hi")) 

Gracias a Daniel S. para la corrección.

+0

¿Qué comportamiento perezoso? –

+0

Tienes razón, olvidé que esto ha cambiado. – Landei

16

Puede crear un método de ayuda

def rep[A](n: Int)(f: => A) { if (n > 0) { f; rep(n-1)(f) } } 

y utilizarla:

rep(5) { println("hi") } 

Basado en @ Jörgs comento que he escrito un momento, tal método:

class Rep(n: Int) { 
    def times[A](f: => A) { loop(f, n) } 
    private def loop[A](f: => A, n: Int) { if (n > 0) { f; loop(f, n-1) } } 
} 
implicit def int2Rep(i: Int): Rep = new Rep(i) 

// use it with 
10.times { println("hi") } 

Based en los comentarios de @DanGordon, he escrito un método de tiempos como ése:

implicit class Rep(n: Int) { 
    def times[A](f: => A) { 1 to n foreach(_ => f) } 
} 

// use it with 
10.times { println("hi") } 
+3

Y obtener desbordamiento de pila cuando 'n' es grande. Al igual que este sitio se llama :) –

+1

Sin embargo, puede ser recursión de cola optimizada por el compilador. Pero no confiaría en eso en la programación del mundo real (por ejemplo, algún día, es posible que desee iniciar sesión en la cola). –

+0

Usted podría simplificar esto al declarar la clase con la palabra clave 'implicit'. De hecho, ni siquiera necesitaría tener la conversión implícita explícita, o el primer método en la clase 'Rep'. – DanGordon

8

Con scalaz 6:

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! 

[fragmento copiado de here.]

+0

¿Cómo se 'arregla' 'times' de esa manera? ¿Es eso un truco avanzado? – Carcigenicate

+0

@Carcigenicate, la respuesta de sschaef demuestra el truco. – missingfaktor

Cuestiones relacionadas