Producto Cartesiano (I)
Como generar un producto cartesiano de dos conjuntos en Scala? Imaginemos que son dos conjuntos de enteros consecutivos, que se pueden representar con la clase Range. Para generar dicho rangos podriamos usar el metodo apply del objeto Range, tal que
scala> val rango = Range(1, 6) rango: scala.collection.immutable.Range with Range.ByOne = Range(1, 2, 3, 4, 5)
Como vemos, el rango es exclusivo en su extremo superior Range(1, 6) corresponde a 1, 2, 3, 4, 5. Otra forma mas vistosa de generar este rango es a traves del metodo to de RichInt.
scala> val rango = 1 to 5 rango: scala.collection.immutable.Range.Inclusive with scala.collection.immutable.Range.ByOne = Range(1, 2, 3, 4, 5)
a diferencia de usar Range(), este metodo es inclusivo; obtenemos el mismo rango usando 1 to 5. Si el metodo to esta definido en RichInt, como es que hemos podido invocarlo sobre 1, que es un Int? Al detectar el compilador la existencia (en el ambito de ejecuccion) de una conversion implicita entre Int y RichInt, este la aplica automaticamente, de manera que los detalles de la conversion son transparentes para el programador. Dicho de otra manera, el programador se beneficia de la implementacion de RichInt casi como si fuera parte de Int.
Una vez obtenidos dos rangos que representan los dos conjuntos solo nos queda obtener el Producto Cartesiano.
scala> val a = 1 to 6 a: scala.collection.immutable.Range.Inclusive with scala.collection.immutable.Range.ByOne = Range(1, 2, 3, 4, 5, 6) scala> val b = 3 to 5 b: scala.collection.immutable.Range.Inclusive with scala.collection.immutable.Range.ByOne = Range(3, 4, 5) scala> for(i <- a; j <- b) yield (i, j) res26: scala.collection.immutable.IndexedSeq[(Int, Int)] = Vector((1,3), (1,4), (1,5), (2,3), (2,4), (2,5), (3,3), (3,4), (3,5), (4,3), (4,4), (4,5), (5,3), (5,4), (5,5), (6,3), (6,4), (6,5))
Esta for comprehension esta generando tuplas de dos elementos (que realmente son instancias de Tuple2) con la sintaxis (x, y). Este ejemplo de for comprehension equivaldria en Java a dos for loops anidados. El for comprehension es una estructura de control que generaliza el concepto de bucle o iteracion permitiendo expresiones de mucha potencia (asemejandose en su capacidad para seleccionar datos, sobre los que luego iterar, a las SELECT’s de SQL). Terminamos con una version en una linea del codigo anterior
scala> for(i <- 1 to 6; j <- 3 to 5) yield (i, j) res27: scala.collection.immutable.IndexedSeq[(Int, Int)] = Vector((1,3), (1,4), (1,5), (2,3), (2,4), (2,5), (3,3), (3,4), (3,5), (4,3), (4,4), (4,5), (5,3), (5,4), (5,5), (6,3), (6,4), (6,5))