Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Returning and iterable collection using yield in scala

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!

like image 869
fbl Avatar asked Oct 28 '11 12:10

fbl


People also ask

How do you use yield in Scala?

yield keyword will returns a result after completing of loop iterations. The for loop used buffer internally to store iterated result and when finishing all iterations it yields the ultimate result from that buffer. It doesn't work like imperative loop.

Why yield is used in Scala?

The yield keyword is used because the result of each for loop iteration is stored in a list (vector) or it collects the list of output and saves it in the vector.

Which expression is one way to iterate over a collection and generate a collection of each iterations result?

forEach() method is available in Java 8 and each collection has this method that implements the iteration internally. Syntax used : With iterable variable.

What is yield in spark?

Yield is a keyword in scala that is used at the end of the loop. We can perform any operation on the collection elements by using this for instance if we want to increment the value of collection by one. This will return us to the new collection.


2 Answers

def dateRange(from : DateTime, to : DateTime, step : TimeSpan): Iterator[DateTime] =
  Iterator.iterate(from)(_ + step).takeWhile(_ <= to)
like image 161
Debilski Avatar answered Sep 30 '22 14:09

Debilski


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))
like image 31
Mr Speaker Avatar answered Sep 30 '22 12:09

Mr Speaker