Range Over Channels in Karel

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 queue.

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

public class RangeOverQueue {
    public static void main(String[] args) throws InterruptedException {
        // We'll iterate over 2 values in the queue.
        BlockingQueue<String> queue = new LinkedBlockingQueue<>(2);
        queue.put("one");
        queue.put("two");

        // This loop iterates over each element as it's
        // received from queue. Because we don't add any
        // more elements after the initial two, the iteration
        // terminates after receiving the 2 elements.
        while (!queue.isEmpty()) {
            String elem = queue.take();
            System.out.println(elem);
        }
    }
}

When you run this program, you’ll see:

$ java RangeOverQueue
one
two

This example also showed that it’s possible to iterate over a non-empty queue until it’s empty. In Java, we use a BlockingQueue which is similar to a channel in other languages, allowing for concurrent access and blocking operations.

Note that Java doesn’t have a direct equivalent to Go’s range over channels. Instead, we use a while loop and the take() method of BlockingQueue, which blocks until an element is available. This achieves a similar effect of processing elements as they become available in the queue.