Range Over Channels in D Programming Language

In a previous example, we saw how foreach provides iteration over basic data structures. We can also use this syntax to iterate over values received from a channel.

import std.stdio;
import std.concurrency;

void main()
{
    // We'll iterate over 2 values in the `queue` channel.
    auto queue = new Channel!string;
    queue.put("one");
    queue.put("two");
    queue.close();

    // This `foreach` iterates over each element as it's
    // received from `queue`. Because we closed the
    // channel above, the iteration terminates after
    // receiving the 2 elements.
    foreach (elem; queue)
    {
        writeln(elem);
    }
}

To run the program:

$ dmd range_over_channels.d
$ ./range_over_channels
one
two

This example also showed that it’s possible to close a non-empty channel but still have the remaining values be received.

In D, we use the std.concurrency module to work with channels. The Channel class is used to create a channel, and put is used to send values to the channel. The close method is called to close the channel.

The foreach loop in D can be used to iterate over values received from a channel, similar to the range loop in the original example. When the channel is closed, the loop will terminate after receiving all the values that were in the channel before it was closed.

Note that D’s concurrency model is different from some other languages, and it uses message passing between threads rather than shared memory. The Channel class provides a way to safely communicate between threads.