diff options
| -rw-r--r-- | source/tanya/algorithm/iteration.d | 175 | ||||
| -rw-r--r-- | source/tanya/range/array.d | 12 |
2 files changed, 97 insertions, 90 deletions
diff --git a/source/tanya/algorithm/iteration.d b/source/tanya/algorithm/iteration.d index 9d95162..8a3686b 100644 --- a/source/tanya/algorithm/iteration.d +++ b/source/tanya/algorithm/iteration.d @@ -435,127 +435,134 @@ if (isInputRange!R) } } -/** - * Iterates a bidirectional range backwards. - * - * If $(D_PARAM Range) is a random-access range as well, the resulting range - * is a random-access range too. - * - * Params: - * Range = Bidirectional range type. - * range = Bidirectional range. - * - * Returns: Bidirectional range with the elements order reversed. - */ -auto retro(Range)(Range range) -if (isBidirectionalRange!Range) +// Reverse-access-order range returned by `retro`. +private struct Retro(Range) { - static struct Retro + Range source; + + @disable this(); + + private this(Range source) { - Range source; + this.source = source; + } - @disable this(); + Retro save() + { + return this; + } - private this(Range source) - { - this.source = source; - } + @property auto ref front() + in (!empty) + { + return this.source.back; + } - Retro save() - { - return this; - } + void popFront() + in (!empty) + { + this.source.popBack(); + } - @property auto ref front() - in (!empty) + @property auto ref back() + in (!empty) + { + return this.source.front; + } + + void popBack() + in (!empty) + { + this.source.popFront(); + } + + @property bool empty() + { + return this.source.empty; + } + + static if (hasLength!Range) + { + @property size_t length() { - return this.source.back; + return this.source.length; } + } - void popFront() - in (!empty) + static if (isRandomAccessRange!Range && hasLength!Range) + { + auto ref opIndex(size_t i) + in (i < length) { - this.source.popBack(); + return this.source[$ - ++i]; } + } - @property auto ref back() + static if (hasAssignableElements!Range) + { + @property void front(ref ElementType!Range value) in (!empty) { - return this.source.front; + this.source.back = value; } - void popBack() + @property void front(ElementType!Range value) in (!empty) { - this.source.popFront(); + this.source.back = move(value); } - @property bool empty() + @property void back(ref ElementType!Range value) + in (!empty) { - return this.source.empty; + this.source.front = value; } - static if (hasLength!Range) + @property void back(ElementType!Range value) + in (!empty) { - @property size_t length() - { - return this.source.length; - } + this.source.front = move(value); } static if (isRandomAccessRange!Range && hasLength!Range) { - auto ref opIndex(size_t i) + void opIndexAssign(ref ElementType!Range value, size_t i) in (i < length) { - return this.source[$ - ++i]; - } - } - - static if (hasAssignableElements!Range) - { - @property void front(ref ElementType!Range value) - in (!empty) - { - this.source.back = value; + this.source[$ - ++i] = value; } - @property void front(ElementType!Range value) - in (!empty) - { - this.source.back = move(value); - } - - @property void back(ref ElementType!Range value) - in (!empty) - { - this.source.front = value; - } - - @property void back(ElementType!Range value) - in (!empty) - { - this.source.front = move(value); - } - - static if (isRandomAccessRange!Range && hasLength!Range) + void opIndexAssign(ElementType!Range value, size_t i) + in (i < length) { - void opIndexAssign(ref ElementType!Range value, size_t i) - in (i < length) - { - this.source[$ - ++i] = value; - } - - void opIndexAssign(ElementType!Range value, size_t i) - in (i < length) - { - this.source[$ - ++i] = move(value); - } + this.source[$ - ++i] = move(value); } } } - return Retro(range); + version (unittest) static assert(isBidirectionalRange!Retro); +} + +/** + * Iterates a bidirectional range backwards. + * + * If $(D_PARAM Range) is a random-access range as well, the resulting range + * is a random-access range too. + * + * Params: + * Range = Bidirectional range type. + * range = Bidirectional range. + * + * Returns: Bidirectional range with the elements order reversed. + */ +auto retro(Range)(return Range range) +if (isBidirectionalRange!Range) +{ + // Special case: retro(retro(range)) is range + static if (is(Range == Retro!RRange, RRange)) + return range.source; + else + return Retro!Range(range); } /// diff --git a/source/tanya/range/array.d b/source/tanya/range/array.d index 3cf68dc..97101b9 100644 --- a/source/tanya/range/array.d +++ b/source/tanya/range/array.d @@ -54,7 +54,7 @@ module tanya.range.array; * * Precondition: $(D_INLINECODE array.length > 0). */ -@property ref T front(T)(T[] array) +@property ref inout(T) front(T)(return scope inout(T)[] array) in { assert(array.length > 0); @@ -94,7 +94,7 @@ do * * Precondition: $(D_INLINECODE array.length > 0). */ -@property ref T back(T)(T[] array) +@property ref inout(T) back(T)(return scope inout(T)[] array) in { assert(array.length > 0); @@ -133,7 +133,7 @@ do * * Precondition: $(D_INLINECODE array.length > 0). */ -void popFront(T)(ref T[] array) +void popFront(T)(scope ref inout(T)[] array) in { assert(array.length > 0); @@ -144,7 +144,7 @@ do } /// ditto -void popBack(T)(ref T[] array) +void popBack(T)(scope ref inout(T)[] array) in { assert(array.length > 0); @@ -178,7 +178,7 @@ do * Returns: $(D_KEYWORD true) if $(D_PARAM array) has no elements, * $(D_KEYWORD false) otherwise. */ -@property bool empty(T)(const T[] array) +@property bool empty(T)(scope const T[] array) { return array.length == 0; } @@ -203,7 +203,7 @@ do * * Returns: A copy of the slice $(D_PARAM array). */ -@property T[] save(T)(T[] array) +@property inout(T)[] save(T)(return scope inout(T)[] array) { return array; } |
