2011-10-31 33 views
18

¿Es posible en Scala especializarse en las condiciones dentro de un if dentro de un para la comprensión? Estoy pensando en la línea de:Declaraciones `if` de comprensión de Scala

val collection: SomeGenericCollection[Int] = ... 

trait CollectionFilter 
case object Even extends CollectionFilter 
case object Odd extends CollectionFilter 

val evenColl = for { i <- collection if(Even) } yield i 
//evenColl would be a SomeGenericEvenCollection instance 

val oddColl = for { i <- collection if(Odd) } yield i 
//oddColl would be a SomeGenericOddCollection instance 

Lo esencial es que, al ceder i, consigo una nueva colección de un tipo potencialmente diferente (por lo tanto me refiriéndose a ella como "especialización") - en lugar de sólo una versión filtrada del mismo tipo de GenericCollection.

La razón por la que pregunto es que vi algo que no pude descifrar (se puede encontrar un ejemplo on line 33 of this ScalaQuery example. Lo que hace es crear una consulta para una base de datos (es decir, SELECT ... FROM ... WHERE ...), donde yo esperaba iterar sobre los resultados de dicha consulta

+0

Esta pregunta no tiene mucho sentido. Voy a responder lo que creo que se lo preguntan, pero trato de mejorarlo. –

+0

['For expressions'] (http://www.artima.com/pins1ed/for-expressions-revisited.html#23.1) debería ayudar. – 4e6

+0

Agregué un poco para tratar de aclarar la pregunta, aunque pareces estar en lo cierto al pensar sobre lo que estaba preguntando. – Dylan

Respuesta

40

Por lo tanto, creo que está preguntando si es posible que la declaración if en una comprensión forzosa cambie el tipo de resultado. La respuesta es "sí, pero. .. ".

Primero, comprenda cómo se expanden las comprensiones. Hay preguntas aquí en Desbordamiento de pila que lo discuten, y hay parámetros que puede pasar al compilador para que le muestre lo que está sucediendo.

De todos modos, este código:

val evenColl = for { i <- collection if(Even) } yield i 

se traduce como:

val evenColl = collection.withFilter(i => Even).map(i => i) 

lo tanto, si el método withFilter cambia el tipo de colección, que va a hacer lo que quiere - en este caso sencillo . En los casos más complejos, que por sí sola no va a funcionar:

for { 
    x <- xs 
    y <- ys 
    if cond 
} yield (x, y) 

se traduce como

xs.flatMap(ys.withFilter(y => cond).map(y => (x, y))) 

En cuyo caso flatMap es decidir qué tipo será devuelto. Si toma la señal de qué resultado fue devuelto, entonces puede funcionar.

Ahora, en Scala Collections, withFilter no cambia el tipo de la colección. Sin embargo, podrías escribir tus propias clases que harían eso.

+0

Gracias, creo que 'withFilter' fue la información clave que me faltaba. – Dylan

4

Sí se puede -... por favor refiérase a this tutorial para un ejemplo sencillo el ejemplo de consulta Scala ha citado también está iterando la colección, entonces se usa esos datos para construir la consulta

Cuestiones relacionadas