2010-04-30 11 views
11

¿Proporciona Scala una clase incorporada, utilidad, sintaxis u otro mecanismo para convertir (al envolver) un iterador con un Iterable?scala conversión implícita o explícita de iterador a iterable

Por ejemplo, tengo un iterador [Foo] y necesito un Iterable [Foo], por lo que actualmente estoy:

val foo1: Iterator[Foo] = .... 
val foo2: Iterable[Foo] = new Iterable[Foo] { 
    def elements = foo1 
} 

Esto parece feo e innecesario. ¿Cuál es una mejor manera?

+0

duplicar http://stackoverflow.com/questions/1072784/how-can-i-convert-a-java-iterable-to-a-scala-iterable – wheaties

+3

@wheaties esto no es una duplicado de esa pregunta. –

Respuesta

12

tiene un método toIterable en Scala 2.8.0, pero no en 2.7.7 o anterior. No es implícito, pero podría definir su propia conversión implícita si la necesita.

7

usted debe ser muy cuidadoso sobre siempre implícitamente convertir una Iterator en un Iterable (normalmente uso Iterator.toList - explícitamente). La razón para esto es que, al pasar el resultado a un método (o función) que espera un Iterable, pierde el control en la medida en que su programa podría estar roto. He aquí un ejemplo:

def printTwice(itr : Iterable[String]) : Unit = { 
    itr.foreach(println(_)) 
    itr.foreach(println(_)) 
} 

Si un Iterator eran de alguna manera convertir implícitamente en un Iterable, lo que será la siguiente imprimiría?

printTwice(Iterator.single("Hello")) 

Será (por supuesto), sólo imprimir Hola vez. Muy recientemente, se ha agregado traitTraversableOnce a la biblioteca de colecciones, que unifica Iterator y Iterable. En mi opinión, esto es posiblemente un error.

Mi preferencia personal es usar Iterator explícita siempre que sea posible y luego usar List, Set o IndexedSeq directamente. He descubierto que rara vez puedo escribir un método que sea genuinamente agnóstico del tipo que se transmite. Un ejemplo:

def foo(trades: Iterable[Trade]) { 
    log.info("Processing %d trades", trades.toList.length) //hmmm, converted to a List 

    val shorts = trades.filter(_.side.isSellShort) 
    log.info("Found %d sell-short", shorts.toList.length) //hmmm, converted to a List again 

    //etc 
+4

Lo he hecho porque su afirmación "Por supuesto, solo imprimirá Hola una vez" es falso. 'ToIterable' de Scala envuelve el iterador en un flujo, lo que garantiza que obtenga la semántica de iteración múltiple adecuada. Esto hace que mucha de tu respuesta sea incorrecta. –

Cuestiones relacionadas