summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/tanya/algorithm/iteration.d175
-rw-r--r--source/tanya/range/array.d12
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;
}