Returning and iterable collection using yield in scala

1.2k views Asked by At

I have a DateTime and TimeSpan class in Scala (assume that the < and + operators work as they should). I'm trying to define a 'range' function that takes a start/stop time and a timespan for stepping. In C# I would do this with a yield, and I think I should be able to do the same in Scala... except I'm getting a strange error.

On the 'yield t' line, I get "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
    }
  }

Looking at this code, I am curious about 2 things: 1) what did I do wrong? 2) the code as written is very imperative (uses a var t, etc). What's the more functional way to do this in Scala that is reasonably fast?

Thanks!

3

There are 3 answers

1
Debilski On BEST ANSWER
def dateRange(from : DateTime, to : DateTime, step : TimeSpan): Iterator[DateTime] =
  Iterator.iterate(from)(_ + step).takeWhile(_ <= to)
1
0__ On

In Scala, yield is a special statement for for-loops.

I don't know C#, but from what I understand, I think the easiest for you is to use collection.immutable.NumericRange.Exclusive[DateTime] or collection.immutable.NumericRange.Inclusive[DateTime], depending on whether your interval is exclusive or inclusive.

For that to work, you will need to create an instance of Integral[DateTime] which defines the arithmetics for type DateTime.

0
Mr Speaker On

Here's a version of @Debilski solution with joda time periods:

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

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