begin, begin + step,
begin + 2 * step, `...`, up to and excluding end.
The two-argument overloads have step = 1. If begin < end && step < 0 or begin > end && step > 0 or begin == end, then an empty range is returned. If step == 0 then begin == end is an error.
For built-in types, the range returned is a random access range. For user-defined types that support `++`, the range is an input range.
in operator and contains: iota over an integral/pointer type defines the in operator from the right. val in iota(...) is true when val occurs in the range. When present, it takes step into account - val won't be considered contained if it falls between two consecutive elements of the range. The contains method does the same as in, but from the left-hand side.
Example: --- void main() { import std.stdio;
// The following groups all produce the same output of: // 0 1 2 3 4
foreach (i; 0 .. 5) writef("%s ", i); writeln();
import std.range : iota; foreach (i; iota(0, 5)) writef("%s ", i); writeln();
writefln("%(%s %|%)", iota(0, 5));
import std.algorithm.iteration : map; import std.algorithm.mutation : copy; import std.format; iota(0, 5).map!(i => format("%s ", i)).copy(stdout.lockingTextWriter()); writeln(); } ---