Range Over Channels in Nim

Our first example demonstrates how to iterate over values received from a channel. This is similar to iterating over basic data structures, but with some key differences specific to channels.

import std/[asyncdispatch, channels]

proc main() {.async.} =
  # We'll iterate over 2 values in the `queue` channel.
  var queue = newChannel[string](2)
  await queue.send("one")
  await queue.send("two")
  queue.close()

  # This `for` loop iterates over each element as it's
  # received from `queue`. Because we closed the
  # channel above, the iteration terminates after
  # receiving the 2 elements.
  for elem in queue.recv():
    echo elem

waitFor main()

To run the program:

$ nim c -r range_over_channels.nim
one
two

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

In Nim, we use the channels module from the standard library to work with channels. The newChannel function creates a new channel with a specified capacity. We use await with send because channel operations are asynchronous in Nim.

The for loop with recv() is used to iterate over the channel’s values. This is equivalent to the range-based for loop in the original example. The loop continues until the channel is closed and all values have been received.

Note that in Nim, we need to wrap our main logic in an async procedure and use waitFor to run it, as channel operations are inherently asynchronous.