2

I have a code snippet like this:

val step = Step.Montyly  //this could be Yearly, daily, hourly, etc.
val (lower, upper) = (****, ****) //unix timestamps, which represent a time range 
val timeArray = Array[Long](0)

var time = lower
while (time <= upper) {
    timeArray +: = time
    time = step.next(time) // eg, Step.Hourly.next(time) = time + 3600, Step.Monthly.next(time) = new DateTime(time).addMonths(1).toTimeStamp()
}

return timeArray

Though this is written in Scala, it is a non-functional way. I'm new to Scala, wondering if this can be rewritten in functional way. I know things like the following:

for(i <- 1 to 10 by step) yield i

But step is a fixed value here, how to make 'i' can be generated by a 'next function' rather than a fixed value?

2 Answers 2

5

You'll have to change the flow a bit to make it functional (without mutable Array and without var). Stream.iterate works with an initial start value, and applies a function repeatedly to generate the next elements.

Stream.iterate(lower)(step.next).takeWhile(_ < upper)
Sign up to request clarification or add additional context in comments.

3 Comments

I like this! Furthermore, the same function is available on List, if one wants a strictly-evaluated solution.
@Reactormonk, thanks! I'm now able to clear non-functional codes in my project. I like this elegant and expressive way :)
@stefanobaghino yeah, but it won't terminate.
1

Reactormonk's answer is probably what I would use in practice, but here's an alternative fully-functional tail-recursive one (taking any step function you like)

  def next(n: Long) = n + 3 // simple example for illustration

  def steps(current: Long, upper: Long, f: Long => Long, result: List[Long]): Array[Long] =
  {
    if (current >= upper)
      result.reverse.toArray
    else 
      steps(f(current), upper, f, current :: result)
  } 
  steps(1, 20, next, List(0))
  //> res0: Array[Long] = Array(0, 1, 4, 7, 10, 13, 16, 19)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.