2011-10-28 3 views
5

Ho una classe DateTime e TimeSpan in Scala (si supponga che gli operatori < e + funzionino come dovrebbero). Sto provando a definire una funzione 'intervallo' che richiede un tempo di avvio/arresto e un intervallo di tempo per lo stepping. In C# lo farei con una resa, e penso che dovrei essere in grado di fare lo stesso in Scala ... eccetto che ho uno strano errore.Ritorno e raccolta iterabile con resa in scala

Sulla riga 'yield t', viene visualizzato "Illegal start of statement".

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 
    } 
    } 

Osservando questo codice, io sono curioso di 2 cose: 1) che cosa ho fatto di sbagliato? 2) il codice come scritto è molto imperativo (usa una var t, ecc.). Qual è il modo più funzionale per farlo in Scala ragionevolmente veloce?

Grazie!

+0

'yield' a Scala non ha nulla a che fare con' yield' in C# (o Python). Inoltre, Scala non ha equivalenti ad esso - guarda le molte domande su Scala, Python, rendimento e generatori. E, naturalmente, cerca le domande su cosa "rendimento" effettivamente fa. –

+0

L'ho fatto, ed ero confuso. La risposta di Debilski mi ha detto tutto quello che dovevo sapere. – fbl

risposta

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

Se potessi darti un +1000, lo farei. È fantastico. – fbl

0

In Scala, yield è una dichiarazione speciale per for-loops.

Non so C#, ma da quello che ho capito, penso che il modo più semplice per voi sia utilizzare collection.immutable.NumericRange.Exclusive[DateTime] o collection.immutable.NumericRange.Inclusive[DateTime], a seconda che l'intervallo sia esclusivo o inclusivo.

Affinché funzioni, è necessario creare un'istanza di Integral[DateTime] che definisce l'aritmetica per il tipo DateTime.

+0

Bene, 'Integral' è una specie di stupido da implementare per' DateTime' sembra. L'altro approccio con 'Iterator.iterate' è molto meglio. –

3

Ecco una versione della soluzione di @Debilski con periodi di tempo 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))