2011-10-28 23 views
5

Mam klasę DateTime i TimeSpan w Scali (zakładam, że operatory < i + działają tak, jak powinny). Próbuję zdefiniować funkcję "zasięgu", która zajmuje czas rozpoczęcia/zakończenia i czas trwania kroku. W języku C# robiłbym to z wydajnością i myślę, że powinienem móc zrobić to samo w Scali ... z wyjątkiem tego, że dostaję dziwny błąd.Zwracająca i możliwa do sprawdzenia kolekcja wykorzystująca wydajność w scala

W linii "yield t" otrzymuję komunikat "Nielegalne rozpoczęcie wyciągu".

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

Patrząc na ten kod, jestem ciekawy o 2 rzeczy: 1) co zrobiłem źle? 2) kod jak napisano jest bardzo pilny (używa var t, etc). Jaki jest bardziej funkcjonalny sposób robienia tego w Scali, który jest dość szybki?

Dzięki!

+0

'yield' w Scala ma nic wspólnego z' yield' w C# (lub Python). Co więcej, Scala nie ma odpowiednika - wyszukaj wiele pytań dotyczących Scali, Pythona, wydajności i generatorów. I, oczywiście, sprawdzić pytania dotyczące tego, co faktycznie oznacza "plon". –

+0

Zrobiłem to i byłem zdezorientowany. Odpowiedź Debilskiego powiedziała mi wszystko, co musiałem wiedzieć. – fbl

Odpowiedz

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

Gdybym mógł dać ci +1000, zrobiłbym to. To cudownie. – fbl

0

W Scali, yield jest specjalnym oświadczeniem dotyczącym pętli for-loop.

Nie znam C#, ale z tego, co rozumiem, myślę, że najłatwiej jest użyć collection.immutable.NumericRange.Exclusive[DateTime] lub collection.immutable.NumericRange.Inclusive[DateTime], w zależności od tego, czy przedział czasowy jest wyłączny, czy wyłączny.

Aby to działało, musisz utworzyć instancję Integral[DateTime], która definiuje arytmetykę dla typu DateTime.

+0

Cóż, 'Integral' jest trochę głupie, aby wdrożyć dla' DateTime' wydaje. Inne podejście z 'Iterator.iterate' jest znacznie lepsze. –

3

Oto wersja rozwiązania @Debilski z okresów 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))