2011-10-28 15 views
5

Tengo una clase DateTime y TimeSpan en Scala (supongamos que los operadores < y + funcionan como deberían). Estoy tratando de definir una función de "rango" que tome un tiempo de inicio/finalización y un intervalo de tiempo para avanzar. En C# lo haría con un rendimiento, y creo que debería poder hacer lo mismo en Scala ... excepto que estoy obteniendo un error extraño.Devolución e iteración de la colección con rendimiento en scala

En la línea 'yield t', aparece el mensaje "Inicio ilegal de la instrucción".

def dateRange(from : DateTime, to : DateTime, step : TimeSpan) = 
    { 
     // not sure what the list'y way of doing this is 
    var t = from 

    while(t < to) 
    { 
     yield t; // error: illegal start of statement 
     t = t + step 
    } 
    } 

En cuanto a este código, tengo curiosidad por 2 cosas: 1) lo que hice mal? 2) el código tal como está escrito es muy imperativo (utiliza una var t, etc.). ¿Cuál es la forma más funcional de hacer esto en Scala que es razonablemente rápido?

Gracias!

+0

'yield' en Scala tiene nada que ver con' yield' en C# (o Python). Además, Scala no tiene equivalente: busque las muchas preguntas sobre Scala, Python, rendimiento y generadores. Y, por supuesto, busque las preguntas sobre qué 'rendimiento' realmente hace. –

+0

Lo hice, y estaba confundido. La respuesta de Debilski me dijo todo lo que necesitaba saber. – fbl

Respuesta

17
def dateRange(from : DateTime, to : DateTime, step : TimeSpan): Iterator[DateTime] = 
    Iterator.iterate(from)(_ + step).takeWhile(_ <= to) 
+0

Si pudiera darle un +1000, lo haría. Eso es genial. – fbl

0

En Scala, yield es una declaración especial para for-loops.

No sé C#, pero por lo que entiendo, creo que lo más fácil para usted es usar collection.immutable.NumericRange.Exclusive[DateTime] o collection.immutable.NumericRange.Inclusive[DateTime], dependiendo de si su intervalo es exclusivo o inclusivo. Para que funcione, necesitará crear una instancia de Integral[DateTime] que defina las aritméticas para el tipo DateTime.

+0

Bueno, 'Integral' es algo estúpido de implementar para' DateTime', parece. El otro enfoque con 'Iterator.iterate' es mucho mejor. –

3

Aquí hay una versión de la solución @Debilski con períodos de tiempo Joda:

import org.joda.time.{DateTime, Period} 

def dateRange(from: DateTime, to: DateTime, step: Period): Iterator[DateTime] = 
    Iterator.iterate(from)(_.plus(step)).takeWhile(!_.isAfter(to)) 
Cuestiones relacionadas