Skip to content

Commit 83bc111

Browse files
committed
[basics/ranges] Improve page
Add basic definition at the top. Tweak wording. Add section for array range. Mention UFCS. Describe range pipelines. Show `import` when using new functions for the first time. Add links.
1 parent e3921c2 commit 83bc111

File tree

1 file changed

+46
-10
lines changed

1 file changed

+46
-10
lines changed

basics/ranges.md

Lines changed: 46 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
# Ranges
22

3-
If a `foreach` is encountered by the compiler
3+
A range produces a series of elements (values) of the same type.
4+
5+
If a [`foreach` statement](basics/foreach) is encountered by the compiler
6+
with an expression recognised as a *range*:
47

58
```
69
foreach (element; range)
@@ -15,48 +18,81 @@ it's internally rewritten similar to the following:
1518
for (auto __rangeCopy = range;
1619
    !__rangeCopy.empty;
1720
    __rangeCopy.popFront())
18-
{
21+
{
1922
   auto element = __rangeCopy.front;
2023
   // Loop body...
2124
}
2225
```
2326

24-
Any object which fulfills the following interface is called a **range**
25-
(or more specific `InputRange`) and is thus a type that can be iterated over:
27+
The remainder of range behaviour is defined in the standard library.
28+
29+
## Range Interface
30+
31+
Any object which has defined the following methods is called an *input range*
32+
and is thus a type that can be iterated over:
2633

2734
```
28-
   interface InputRange(E)
35+
interface InputRange(E)
2936
{
3037
bool empty();
3138
E front();
3239
void popFront();
3340
}
3441
```
3542

43+
`E` is the element type of the range.
44+
45+
A [dynamic array](basics/arrays) can be a range by importing `std.range`.
46+
This module defines range primitives on arrays, which can be called by
47+
[UFCS](gems/uniform-function-call-syntax-ufcs):
48+
49+
```
50+
import std.range;
51+
52+
int[] a = [1, 2, 3];
53+
assert(!a.empty);
54+
assert(a.front == 1);
55+
a.popFront();
56+
assert(a == [2, 3]);
57+
```
58+
3659
Have a look at the example on the right to inspect the implementation and usage
37-
of an input range closer.
60+
of a custom input range.
3861

3962
## Laziness
4063

4164
Ranges are __lazy__. They won't be evaluated until requested.
42-
Hence, a range from an infinite range can be taken:
65+
Hence, a range can produce infinite elements.
66+
67+
Below a range is created by calling `repeat`, which produces infinite
68+
elements, each the same as its initial argument. That range is
69+
processed by `take`, which will select the first N elements.
70+
Range functions are often called in a 'pipeline' style using
71+
[UFCS](gems/uniform-function-call-syntax-ufcs) chains:
4372

4473
```d
74+
import std.range;
75+
4576
42.repeat.take(3).writeln; // [42, 42, 42]
4677
```
4778

4879
## Value vs. Reference types
4980

50-
If the range object is a value type, then range will be copied and only the copy
51-
will be consumed:
81+
If the range object is a [value type](basis/structs), then the range will be
82+
copied when passing it as a value parameter to a function, and only the copy
83+
will be consumed.
84+
85+
Below `iota` produces a struct value instance, and `drop` accepts it by value:
5286

5387
```d
88+
import std.range;
89+
5490
auto r = 5.iota;
5591
r.drop(5).writeln; // []
5692
r.writeln; // [0, 1, 2, 3, 4]
5793
```
5894

59-
If the range object is a reference type (e.g. `class` or [`std.range.refRange`](https://dlang.org/phobos/std_range.html#refRange)),
95+
If the range object is a reference type (e.g. [`class`](basics/classes) or [`std.range.refRange`](https://dlang.org/phobos/std_range.html#refRange)),
6096
then the range will be consumed and won't be reset:
6197

6298
```d

0 commit comments

Comments
 (0)