Reputation: 211
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?
Upvotes: 2
Views: 889
Reputation: 21690
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)
Upvotes: 5
Reputation: 41749
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)
Upvotes: 1