comprehension - Scala "<-" para comprensión
for yield scala (3)
He descubierto que Scala siempre tiene una "explicación natural" para cualquier cosa. Siempre algo como "ohh, pero eso es solo una función que se llama en este y ese objeto con este y ese parámetro". En cierto sentido, nada es realmente compilador, como lo conocemos desde otros idiomas.
Mi pregunta es sobre el operador <- como se usa en el siguiente código:
for(i <- 0 to 10) println(i)
En este ejemplo, puedo ver que se reescribe a algo así como:
0.to(10).foreach((i:Int)=>println(i))
pero esto no explica cómo fui llevado a la función anónima dentro de la función foreach. En el punto donde escribes i, no es un objeto, y aún no es una variable declarada. Entonces, ¿qué es y cómo se transmite al interior de Foreach?
Creo que finalmente descubrí algo que, de hecho, es magia de compilación
Gracias por tu tiempo.
Para aclarar, mi pregunta es: ¿cómo funciona el operador <- en la primera línea de código ya que no es un objeto sobre el que se puede llamar como una función.
En este caso, realmente es un poco de magia de compilación. La traducción de for-comprehension a filter / map / flatmap form es un proceso especial de desugaring, muy parecido a la conversión de las formas especiales de actualización y aplicación de métodos.
Para aumentar la respuesta de Dave, aquí hay un esquema de traducción para ''for-comprehensions'' de la especificación del lenguaje Scala:
Una comprensión
for (enums) yield eevalúa la expresiónepara cada enlace generado por los enumeradores enumerados. Una secuencia de enumerador siempre comienza con un generador; esto puede ser seguido por generadores adicionales, definiciones de valores o guardias.Un generador
p <- eproduce enlaces a partir de una expresióneque coincide de alguna manera con el patrónp. Una definición de valorval p = evincula el nombre de valorp(o varios nombres en un patrónp) al resultado de evaluar la expresióne. Un guardiánif econtiene una expresión booleana que restringe los enlaces enumerados.El significado preciso de generadores y guardias se define mediante la traducción a invocaciones de cuatro métodos:
map,filter,flatMapyforeach. Estos métodos se pueden implementar de diferentes maneras para diferentes tipos de operadores.El esquema de traducción es el siguiente. En un primer paso, cada generador
p <- e, donde p no es irrefutable (§8.1) para el tipo deese reemplaza por
p <- e.filter { case p => true; case _ => false }Luego, las siguientes reglas se aplican repetidamente hasta que se hayan eliminado todas las comprensiones.
Una for-comprensión
for (p <- e) yield e0se traduce ae.map { case p => e0 }.Una for-comprensión
for (p <- e) e0se traduce ae.foreach { case p => e0 }.Una for-comprensión
for (p <- e; p0 <- e0 . . .) yield e00, donde. . . es una secuencia (posiblemente vacía) de generadores o guardias, se traduce a:
e.flatMap { case p => for (p0 <- e0 . . .) yield e00 }.A for-understanding
for (p <- e; p0 <- e0 . . .) e00donde. . . es una secuencia (posiblemente vacía) de generadores o guardias, se traduce a:
e.foreach { case p => for (p0 <- e0 . . .) e00 }.Un generador
p <- eseguido de un guardiaif gse traduce a un solo generador:
p <- e.filter((x1, . . . , xn) => g )
dondex1. . ,xnson las variables libres dep.Un generador
p <- eseguido de una definición de valorval p0 = e0se traduce al siguiente generador de pares de valores, dondexyx0son nombres nuevos:
val (p, p0) <- for(x@p <- e) yield { val x0@p0 = e0; (x, x0) }
<- es un símbolo de palabra clave definido por el idioma, como is => pero en claro contraste con -> (que es un símbolo definido). Debido a que es parte de la gramática básica de Scala, se puede usar para crear enlaces (para el i en su ejemplo) que es algo que no se puede hacer mediante construcciones definidas por el usuario.