2010-12-16 7 views
53

Estoy trabajando en Programming in Scala, y aunque estoy tentado de ver las cosas desde la perspectiva de Python, no quiero programar "Python en Scala".para expresiones frente a foreach en Scala

No estoy seguro de qué hacer en cuanto a control de flujo: en Python, usamos for x in some_iterable hasta la muerte, y nos encanta. Existe una construcción muy similar en Scala que Odersky llama para la expresión , probablemente para distinguirla del bucle de Java for. Además, Scala tiene un atributo foreach (supongo que sería un atributo, no sé lo suficiente sobre Scala para nombrarlo correctamente) para tipos de datos iterables. No parece que pueda usar foreach para hacer mucho más que llamar a una función para cada artículo en el contenedor.

Esto me deja con algunas preguntas. Primero, para las expresiones construcciones importantes/muy utilizadas en Scala como en Python, y segundo, ¿cuándo debería usar foreach en lugar de una expresión para (que no sea el caso obvio de invocar una función en cada elemento de un contenedor)?

Espero que no sea terriblemente ambiguo o demasiado amplio, pero estoy tratando de asimilar algunos de los fundamentos del diseño/lenguaje en Scala (lo cual parece muy bueno hasta ahora).

Respuesta

58

python usa for en la lista de comprensiones y expresiones de generador. Esos son muy similar a la expresión Scala for:

esto es pitón

>>> letters = ['a', 'b', 'c', 'd'] 
>>> ints = [0, 1, 2, 3] 
>>> [l + str(i) for l in letters for i in ints if i % 2 == 0] 
['a0', 'a2', 'b0', 'b2', 'c0', 'c2', 'd0', 'd2'] 

esto es Scala

scala> val letters = List('a', 'b', 'c', 'd') 
scala> val ints = List(0, 1, 2, 3) 
scala> for (l <- letters; i <- ints if i % 2 == 0) yield l.toString + i 
res0: List[java.lang.String] = List(a0, a2, b0, b2, c0, c2, d0, d2) 

Cada construcción puede tomar una serie de generadores/iteradores , aplica expresiones de filtros y produce una expresión combinada. En el pitón (expr for v1 in gen1 if expr1 for v2 in gen2 if expr2) es más o menos equivalente a:

for v1 in gen1: 
    if expr1: 
    for v2 in gen2: 
     if expr2: 
     yield expr 

en Scala for (v1 <- gen1 if expr1; v2 <- gen2 if expr2) yield expr es más o menos equivalente a:

gen1.withFilter(expr1).flatMap(v1 => gen2.withFilter(expr2).map(v2 => expr)) 

Si te gusta la sintaxis de Python for x in xs, es probable que va a encantar la Scala for expresión.

Scala tiene algunos giros de sintaxis y traducción adicionales. Sintaxis sabia for se puede utilizar con llaves para que pueda poner las declaraciones en líneas separadas. También puede realizar asignaciones de valores.

val res = for { 
    i <- 1 to 20; i2 = i*i 
    j <- 1 to 20; j2 = j*j 
    k <- 1 to 20; k2 = k*k 
    if i2 + j2 == k2 
    } yield (i, j, k) 

también v1 <- gen1 realmente lleva a cabo un partido case v1 => gen1. Si no hay coincidencia, esos elementos se ignoran de la iteración.

scala> val list = List(Some(1), None, Some(2)) 
scala> for (Some(i) <- list) yield i 
res2: List[Int] = List(1, 2) 

Creo que for tiene un lugar importante en el idioma. ¡Puedo decir que hay un capítulo entero (23) al respecto en el libro que estás leyendo!

+2

Esta es realmente una excelente respuesta. Me alegro de haber esperado unas horas antes de aceptar cualquier cosa. –

3

Con su soporte para iteración anidada, filtros y transformación, diría que el for de Scala es uno de los puntos fuertes del lenguaje y muy central. Tiendo a preferir el uso de foreach, map y filter.

3

El foreach es un estilo funcional, mientras que el for es un estilo imperativo. Si alguna vez has hecho algún ceceo o esquema, ya estás familiarizado con la programación funcional. Si no lo has hecho, puede ser un poco confuso al principio. Lo primero que haría es leer sobre la sintaxis de cierre, que son funciones anónimas que se pasan a cosas como foreach. Una vez que entiendas que todo tendrá más sentido.

3

Sus preguntas se responden en gran medida por el siguiente:

Scala's For Comprehensions

Scala Yield

Para summaraize: Es en gran medida estilística. Personalmente, estoy a favor de la metodología funcional, pero prefiero la concisión de las comprensiones cuando se trata de bucles anidados.

24

Sí, Scala for Comprehensions (como se les conoce comúnmente) se usan mucho, pero en realidad son solo azúcar sintáctica para una combinación particular de métodos, y muchos prefieren llamar estos métodos directamente en lugar de usar el azúcar sintáctico.

Para comprender mejor Scala para las comprensiones, consulte this question. En particular, verá que for (x <- xs) f(x) es lo mismo que xs.foreach(x => f(x)).

Ahora, usted menciona que usted no parece mucho uso con foreach método, pero voy a señalar que casi todos los métodos de colecciones Scala son (o pueden ser) implementado con sólo foreach. Consulte la documentación para Traversable - todos sus métodos se pueden implementar con solo foreach.

Tenga en cuenta que de Scala yield tiene ninguna semejanza con Python yield - se puede mirar hacia arriba that pregunta también.

Cuestiones relacionadas