www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - how do I implement opSlice for retro range?

reply Jack <jckj33 gmail.com> writes:
How can I implement ranges in the retro range? I'd like to do 
this without allocate a new array with .array from std.array, can 
I do that?

use like this:

```d
     auto arr = [1, 2, 3, 4, 5];
     auto a = new A!int(arr);
     auto b = a.retro[0 .. 2]; // 4, 5
```

the class:

```d

class A(T)
{
     private T[] arr;

     this(T[] a)
     {
         arr = a;
     }

     auto opIndex() nothrow
     {
         return Range(arr);
     }

     auto retro() { return RangeRetro(arr); }

     protected static struct Range
     {
         T[] a;
         T front() { return a[0]; }
         T back() { return a[$ - 1]; }
         void popFront() { a = a[1 .. $]; }
         bool empty() { return a.length == 0; }
     }

     protected static struct RangeRetro
     {
         import std.range : popFront;
         import std.range : popBack;

         T[] a;
         T front() { return a[$ - 1]; }
         T back() { return a[0]; }
         void popBack() {  a.popFront(); }
         void popFront() { a.popBack(); }
         bool empty() { return a.length == 0; }

         auto opSlice(size_t start, size_t end)
         {
            ???
         }
     }
}
```
May 13
next sibling parent Jack <jckj33 gmail.com> writes:
sorry, in this code i mean b must be [5, 4]

 ```d
     auto arr = [1, 2, 3, 4, 5];
     auto a = new A!int(arr);
     auto b = a.retro[0 .. 2]; //5,4
 ```
May 13
prev sibling next sibling parent reply =?UTF-8?Q?Christian_K=c3=b6stlin?= <christian.koestlin gmail.com> writes:
On 2021-05-14 05:49, Jack wrote:
 How can I implement ranges in the retro range? I'd like to do this 
 without allocate a new array with .array from std.array, can I do that?
 
 use like this:
 
 ```d
      auto arr = [1, 2, 3, 4, 5];
      auto a = new A!int(arr);
      auto b = a.retro[0 .. 2]; // 4, 5
 ```
 
 the class:
 
 ```d
 
 class A(T)
 {
      private T[] arr;
 
      this(T[] a)
      {
          arr = a;
      }
 
      auto opIndex() nothrow
      {
          return Range(arr);
      }
 
      auto retro() { return RangeRetro(arr); }
 
      protected static struct Range
      {
          T[] a;
          T front() { return a[0]; }
          T back() { return a[$ - 1]; }
          void popFront() { a = a[1 .. $]; }
          bool empty() { return a.length == 0; }
      }
 
      protected static struct RangeRetro
      {
          import std.range : popFront;
          import std.range : popBack;
 
          T[] a;
          T front() { return a[$ - 1]; }
          T back() { return a[0]; }
          void popBack() {  a.popFront(); }
          void popFront() { a.popBack(); }
          bool empty() { return a.length == 0; }
 
          auto opSlice(size_t start, size_t end)
          {
             ???
          }
      }
 }
 ```
 
 
arr.retro()[0..2] already works. see https://run.dlang.io/is/U8u3br
May 14
parent Jack <jckj33 gmail.com> writes:
On Friday, 14 May 2021 at 10:00:44 UTC, Christian Köstlin wrote:
 On 2021-05-14 05:49, Jack wrote:
 [...]
arr.retro()[0..2] already works. see https://run.dlang.io/is/U8u3br
oh, how i silly of i didn't notice that before
May 14
prev sibling parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 5/13/21 11:49 PM, Jack wrote:
 How can I implement ranges in the retro range? I'd like to do this 
 without allocate a new array with .array from std.array, can I do that?
 
 use like this:
 
 ```d
      auto arr = [1, 2, 3, 4, 5];
      auto a = new A!int(arr);
      auto b = a.retro[0 .. 2]; // 4, 5
 ```
 
 the class:
 
 ```d
 
 class A(T)
 {
      private T[] arr;
 
      this(T[] a)
      {
          arr = a;
      }
 
      auto opIndex() nothrow
      {
          return Range(arr);
      }
 
      auto retro() { return RangeRetro(arr); }
 
      protected static struct Range
      {
          T[] a;
          T front() { return a[0]; }
          T back() { return a[$ - 1]; }
          void popFront() { a = a[1 .. $]; }
          bool empty() { return a.length == 0; }
      }
 
      protected static struct RangeRetro
      {
          import std.range : popFront;
          import std.range : popBack;
 
          T[] a;
          T front() { return a[$ - 1]; }
          T back() { return a[0]; }
          void popBack() {  a.popFront(); }
          void popFront() { a.popBack(); }
          bool empty() { return a.length == 0; }
 
          auto opSlice(size_t start, size_t end)
          {
             ???
          }
      }
 }
 ```
 
 
Just slice the `a`, appropriately. You have to translate the indexes back into the original array. ```d auto opSlice(size_t start, size_t end) { return typeof(this)(a[$ - end .. $ - start]); } ``` You should also define `length`, `save`, `opIndex`, and `opDollar` so that it fits in the range hierarchy as a proper random-access range. But I question whether you shouldn't just use `std.range.retro` directly? It does all this for you: ```d // inside A auto retro() { import std.range : retro; return arr.retro; } ``` -Steve
May 14
parent Jack <jckj33 gmail.com> writes:
On Friday, 14 May 2021 at 14:14:03 UTC, Steven Schveighoffer 
wrote:
 On 5/13/21 11:49 PM, Jack wrote:
 [...]
Just slice the `a`, appropriately. You have to translate the indexes back into the original array. ```d auto opSlice(size_t start, size_t end) { return typeof(this)(a[$ - end .. $ - start]); } ``` You should also define `length`, `save`, `opIndex`, and `opDollar` so that it fits in the range hierarchy as a proper random-access range. But I question whether you shouldn't just use `std.range.retro` directly? It does all this for you: ```d // inside A auto retro() { import std.range : retro; return arr.retro; } ``` -Steve
much easier, I'll be just using the one from std.range. Thanks!
May 14