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