2009-09-06 15 views
19

Cuando comencé a buscar en Scala, me gustó el aspecto de las for-comprehensions. Parecían ser un poco como los bucles foreach a los que estaba acostumbrado desde Java 5, pero con restricciones funcionales y mucha dulzura sintáctica dulce.Comprensiones de Scala: ¿característica vital o azúcar sintáctico?

Pero como he absorbido el estilo Scala, me parece que cada vez que podía usar una comprension de que estoy usando map, flatMap, filter, reduce y foreach lugar. La intención del código me parece más clara de esa manera, con menos posibles sorpresas ocultas, y también suelen ser códigos más cortos.

Hasta donde yo sé, las comprensiones siempre se compilan en estos métodos de todos modos, así que me pregunto: ¿para qué sirven en realidad? ¿Me estoy perdiendo alguna actualización funcional (no sería la primera vez)? ¿Los for-comprehensions hacen algo que las otras características no pueden, o al menos serían mucho más torpes? ¿Brillan en un caso de uso particular? ¿Es realmente solo una cuestión de gusto personal?

+2

Esto es casi un duplicado del http://stackoverflow.com/questions/1052476/can-alguien-explique-scalas-rendimiento. Esa pregunta se preguntaba qué significaba 'rendimiento', este se pregunta cuál es su propósito. Las respuestas son casi iguales. –

Respuesta

13

Consulte this question. La respuesta corta es que las comprensiones pueden ser más legibles. En particular, si tiene muchos generadores anidados, el alcance real de lo que está haciendo se vuelve más claro, y no necesita grandes sangrías.

10

para-comprehensions son azúcar sintáctico, pero eso no significa que no sean vitales. Por lo general, son más concisos que su forma expandida, lo que es bueno, pero quizás lo más importante es que ayudan a los programadores de lenguajes imperativos a usar constructos funcionales.

Cuando comencé con Scala, usé mucho las comprensiones porque me resultaban familiares. Luego, casi me detengo por completo, porque tenía ganas de usar los métodos subyacentes, era más explícito y, por lo tanto, más claro. Ahora vuelvo a usar las comprensiones porque creo que es mejor que expresen la intención de lo que estoy haciendo que los medios para hacerlo.

3

Tienes razón. La comprensión es azúcar sintáctica. Creo que los métodos subyacentes son más concisos y fáciles de leer, una vez que esté acostumbrado a ellos.

Compare las siguientes declaraciones equivalentes:

1. for (i <- 1 to 100; if (i % 3 == 0)) yield Math.pow(i, 2) 
2. (1 to 100).filter(_ % 3 == 0).map(Math.pow(_, 2)) 

En mi opinión, la adición del punto y coma en el # 1 distrae de la sensación de que este es un único estado encadenado. También existe la sensación de que i es una var (¿es 1, o es 99, o algo en el medio?) Lo que resta valor a un estilo funcional.

La opción 2 es más evidentemente una cadena de llamadas a métodos en objetos. Cada enlace en la cadena indica claramente su responsabilidad. No hay variables intermedias.

Tal vez para las comprensiones se incluyen como una conveniencia para los desarrolladores de transición de Java. De todos modos, lo que se elige es una cuestión de estilo y preferencia.

+0

"una vez que estés acostumbrado a ellos" - exactamente. Una vez que entendí las mónadas, cambié a los métodos subyacentes. La comprensión fue un enlace útil antes de eso. –

+1

No necesita punto y coma en 1 en absoluto: 'para (i <- 1 a 100 si (i% 3 == 0)) produce Math.pow (i, 2)'. Además, puede reemplazar paréntesis con llaves para activar la inferencia de punto y coma. – Blaisorblade

+0

Gracias @Blaisorblade Me pregunto si el punto y coma fue necesario en 2009. – Synesso

11

Otro gran uso de la comprensión es para DSL interno. ScalaQL es un gran ejemplo de esto. Se puede convertir este

val underAge = for { 
    p <- Person 
    c <- Company 
    if p.company is c 
    if p.age < 14 
} yield p 

en este

SELECT p.* FROM people p JOIN companies c ON p.company_id = c.id WHERE p.age < 14 

y mucho más.

+0

@Erik Funcionó cuando lo probé. Es un enlace a un archivo PDF. Si todavía no puede descargar el archivo, simplemente escríbalo en google: ScalaQL: consultas de base de datos integradas por idioma para Scala por Daniel Spiewak y Tian Zhao –

+0

Downvoted: la pregunta real es si hay alguna ventaja de las comprensiones sobre su desugaring - y puedes escribir ese código también en forma desacralizada. ScalaQuery es un mejor ejemplo, ya que tiene una implementación de calidad de producción disponible. Ese documento vislumbra demasiados detalles importantes para recomendar. – Blaisorblade

5

En algunos casos, para las comprensiones puede expresar la intención mejor, así que cuando lo hagan, úselas.

También tenga en cuenta que con respecto a las comprensiones, obtiene coincidencia de patrón de forma gratuita. Por ejemplo, la iteración en un mapa es mucho más sencillo con la comprensión:

for ((key, value) <- map) println (key + "-->" + value)

que con foreach:

map foreach { case (key, value) => println (key + "-->" + value) }

Cuestiones relacionadas