Range Over Channels in Scala
In a previous example, we saw how for
and foreach
provide iteration over basic data structures. We can also use similar syntax to iterate over values received from a channel.
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.{Future, Await}
import scala.concurrent.duration._
object RangeOverChannels {
def main(args: Array[String]): Unit = {
// We'll iterate over 2 values in the `queue` channel.
val queue = new java.util.concurrent.LinkedBlockingQueue[String]()
queue.put("one")
queue.put("two")
// This `Future` simulates the behavior of ranging over a channel
val future = Future {
Iterator.continually(queue.poll(100, java.util.concurrent.TimeUnit.MILLISECONDS))
.takeWhile(_ != null)
.foreach(println)
}
// Wait for the Future to complete
Await.result(future, 5.seconds)
}
}
To run the program:
$ scala RangeOverChannels.scala
one
two
In this Scala example, we’ve simulated the behavior of Go’s channel range using a LinkedBlockingQueue
and a Future
. The Iterator.continually
with takeWhile
mimics the channel’s behavior of continuing until it’s closed.
This example also shows that it’s possible to add elements to a queue and still process them even after we’ve stopped adding new elements. The poll
method with a timeout allows us to simulate the behavior of a closed channel in Go.
Note that Scala doesn’t have built-in channels like Go, so we’ve used Java’s concurrent utilities to achieve similar functionality. In real-world scenarios, you might want to use Scala’s Akka library for more robust and idiomatic concurrent programming.