Movatterモバイル変換


[0]ホーム

URL:


DLang LogoDLang Tour
Menu

Ranges

If aforeach is encountered by the compiler

foreach (element; range){    // Loop body...}

it's internally rewritten similar to the following:

for (auto __rangeCopy = range;     !__rangeCopy.empty;     __rangeCopy.popFront()) {    auto element = __rangeCopy.front;    // Loop body...}

Any object which fulfills the following interface is called arange(or more specificInputRange) and is thus a type that can be iterated over:

    interface InputRange(E)    {        bool empty();        E front();        void popFront();    }

Have a look at the example on the right to inspect the implementation and usageof an input range closer.

Laziness

Ranges arelazy. They won't be evaluated until requested.Hence, a range from an infinite range can be taken:

42.repeat.take(3).writeln; // [42, 42, 42]

Value vs. Reference types

If the range object is a value type, then range will be copied and only the copywill be consumed:

auto r = 5.iota;r.drop(5).writeln; // []r.writeln; // [0, 1, 2, 3, 4]

If the range object is a reference type (e.g.class orstd.range.refRange),then the range will be consumed and won't be reset:

auto r = 5.iota;auto r2 = refRange(&r);r2.drop(5).writeln; // []r2.writeln; // []

CopyableInputRanges areForwardRanges

Most of the ranges in the standard library are structs and so foreachiteration is usually non-destructive, though not guaranteed. If thisguarantee is important, a specialization of anInputRange can be used—forward ranges with a.save method:

interface ForwardRange(E) : InputRange!E{    typeof(this) save();}
// by value (Structs)auto r = 5.iota;auto r2 = refRange(&r);r2.save.drop(5).writeln; // []r2.writeln; // [0, 1, 2, 3, 4]

ForwardRanges can be extended to Bidirectional ranges + random access ranges

There are two extensions of the copyableForwardRange: (1) a bidirectional rangeand (2) a random access range.A bidirectional range allows iteration from the back:

interface BidirectionalRange(E) : ForwardRange!E{     E back();     void popBack();}
5.iota.retro.writeln; // [4, 3, 2, 1, 0]

A random access range has a knownlength and each element can be directly accessed.

interface RandomAccessRange(E) : ForwardRange!E{     E opIndex(size_t i);     size_t length();}

The best known random access range is D's array:

auto r = [4, 5, 6];r[1].writeln; // 5

Lazy range algorithms

The functions instd.range andstd.algorithm providebuilding blocks that make use of this interface. Ranges enable thecomposition of complex algorithms behind an object thatcan be iterated with ease. Furthermore, ranges enable the creation oflazyobjects that only perform a calculation when it's really neededin an iteration e.g. when the next range's element is accessed.Special range algorithms will be presented later in theD's Gems section.

In-depth

rdmd playground.d


[8]ページ先頭

©2009-2025 Movatter.jp