Reading — step 1 of 5
Learn
~1 min readTemplates and Ranges
D's ranges replace iterators with a simpler 3-method protocol:
struct InputRange {
bool empty();
T front();
void popFront();
}
Any type with these methods works with foreach, Range.map, etc.
Custom range:
struct Counter {
int current = 0;
int max;
bool empty() { return current >= max; }
int front() { return current; }
void popFront() { current++; }
}
foreach (n; Counter(0, 5)) writeln(n); // 0, 1, 2, 3, 4
Range types (capability levels):
- InputRange — single forward pass
- ForwardRange — can save and replay (
save()) - BidirectionalRange — can iterate from either end
- RandomAccessRange —
[i]indexing in O(1)
Most arrays satisfy RandomAccessRange.
Composing ranges with std.range and std.algorithm:
import std.range;
import std.algorithm;
import std.array;
auto result = iota(1, 11) // [1, 2, ..., 10]
.filter!(n => n % 2 == 0)
.map!(n => n * n)
.take(3)
.array; // [4, 16, 36]
Ranges are lazy — nothing computes until consumed. The .array materializes; .filter!, .map!, .take are all wrappers.
Useful helpers:
iota(start, end)— like Python'srangechain(a, b)— concatenatezip(a, b)— pair upenumerate(r)— yield(index, element)chunks(r, n)— break into N-sized pieces
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…