Repeating loop within a for comprehension

#1

Is there an easy way to create a finite cycle within a for comprehension?

for{
  x <- xs
  y =??? 
  z <- zs
}

I’d like y to iterate through for example 1, 2, 3, 1, 2, 3… Another example is that a variable alternates true/false. I cannot use y <- some_iterator because that would make a concentric y-loop.
I encounter a requirement like this from time to time, and I usually convert it to a foldLeft, losing readability.

I’m probably motivated by a feature in Common Lisp loop which would translate to the Scala for comprehension something like the following. The then (meaning thereafter) part is evaluated each time (after the first) through the loop with the variable y bound to its value in the previous iteration.

for{
  x <- xs
  y = 1 then ((y + 1) % 2)
  z <- zs
}

alternatively

for{
  x <- xs
  y = true then !y
  z <- zs
}
#2

There is no primitive that does quite that – I would zip on the previous generator.

val ys = Iterator.unfold(1)(y => Some(y, ((y + 1) % 2))

for {
  (x, y) <- xs.zip(ys)
  z <- zs
}

val ys = true #:: false #:: ys

for {
  (x, y) <- xs.zip(ys)
  z <- zs
}
#3

What’s Iterator.unfold?

#4

It’s like a “reverse fold”: you take a starting value, and a function that takes this value to generate an element and the next function input (as a tuple wrapped in an Option).

In this example, you start with 1, and the function returns Some((1,0)). The first value of that tuple is the element returned by the iterator, the second is the value passed to the function for the next element. So by passing 0 to the function, we then get Some((0, 1)). This results in an infinite Iterator, returning alternating zeros and ones.

To create a finite iterator, the function would return a None to end it.

#5

Okay, but where does it come from? I don’t see it in the Iterator companion object.

#6

That’s because you don’t live in the Glorious Future yet.

https://scala-lang.org/files/archive/api/2.13.x/scala/collection/Iterator$.html#unfoldA,S(f:S=%3EOption[(A,S)]):Iterator[A]

#7

I’ve added this to the Scala Contributors forum, in case anyone would like to follow there and give your thumbs up.