takeBack() implementation in std.range for OutputRanges

Salih Dincer salihdb at hotmail.com
Sat Aug 31 17:55:17 UTC 2024


Why have a function called dropBack() but not takeBack()?
---

**Rationale:** It uses the drop() function in the module and is 
compatible with the name dropBack().

Let's say we have a range (called STS for short) that returns odd 
numbers:

```d
alias STS = SonsuzTekSayı;
struct SonsuzTekSayı { // InfinityNumbers
   import std.traits;
   import std.bigint;

   BigInt numara;
   size_t length;

   this(T)(T ilk) { // Initialize
     static if (isIntegral!T)
       numara = BigInt(ilk % 2 ? ilk : ++ilk);
     else {
       import std.string : isNumeric;
       if (ilk.isNumeric) {
         auto birler = cast(char)ilk.back;
         if (birler % 2 == 0) ++birler;
         ilk.length--;
         numara = BigInt(ilk ~ birler);
       }
     }
   }
   bool empty;
   auto front() => numara;
   auto popFront() => numara += 2;
}
```

Let's add a convenience function to increase efficiency:

```d
alias adetSayıVer = startingFrom;
auto startingFrom(T)(size_t Length, T First)
{
   import std.range : take;

   auto range = STS(First);
   range.length = Length;

   return range.take(Length);
}
```

Since our range is not Bidirectional, we get an error with 
```dropBack()```. Also, we cannot pop 4 elements from the end 
like we do in an array (```arr[$ - 4..$]```), my solution is (if 
it gives the range length) the following:

```d
auto takeBack(R)(R range, size_t n)
{
   import std.range : drop;

   auto diff = range.length - n;

   return range.drop(diff);
}

void main()
{
   import std.stdio : writeln;
   auto r = 1000.startingFrom("9000");

   r.takeBack(4).writeln; /* PRINTS:

     [10993, 10995, 10997, 10999]

   */
}
```

**FN:** Although it is not needed at all, takeBack() already 
works with an array. Perhaps the slicing method for arrays could 
be adapted with or without a convenience function.

SDB at 79


More information about the dip.ideas mailing list