2011-04-29 9 views
7

Con Scala 2.8.1, compilación de este:¿Por qué no se compila esta Scala for expression using tuples?

val t = (40, 2) 

println(for ((i, j) <- List(t)) yield i + j) 

val e: Either[String, (Int, Int)] = Right(t) 
println(e.right.map { 
    case (i, j) => i + j 
}) 
println(for ((i, j) <- e.right) yield i + j) 

da esto:

test.scala:9: error: constructor cannot be instantiated to expected type; 
found : (T1, T2) 
required: Either[Nothing,(Int, Int)] 
println(for ((i, j) <- e.right) yield i + j) 

Según Programación en Scala, la expresión debe ser equivalente a la expresión mapa/caso, pero solo este último compila. ¿Qué estoy haciendo mal y cómo debo hacer esto?

Respuesta

11

En realidad, eso no es bastante la traducción que está sucediendo. Puede consultar el this answer para obtener una guía más completa, pero este caso no se menciona explícitamente allí.

Lo que sucede es que una para la comprensión con patrón de coincidencia filtra la caja que no coincide. Por ejemplo,

for((i, j) <- List((1, 2), 3)) yield (i, j) 

regresará List((1, 2)): List[(Any, Any)], como withFilter se llama en primer lugar. Ahora, Either no parecen tener withFilter, por lo que utilizará filter, y aquí está la traducción real de que, para la comprensión:

e.right.filter { case (i, j) => true; case _ => false }.map { case (i, j) => i + j } 

cual da exactamente el mismo error. El problema es que e.right devuelve RightProjection, pero filter en RightProjection[A, B] devuelve Option[Either[Nothing, B]].

La razón de esto es que no hay tal cosa como un "vacío" Either (o RightProjection), por lo que necesita para encapsular su resultado en una Option.

Habiendo dicho todo eso, es realmente sorprendente cuando se mira el nivel de comprensión. Creo que lo correcto sería que filter devuelva algún tipo de proyección filtrada.

2

Right no devuelve la opción que podría esperar, sino una RightProjection. Esto lo arregla:

println(for ((i, j) <- e.right.toOption) yield i + j) 
Cuestiones relacionadas