Ranges

Emanuele Torre torreemanuele6 at gmail.com
Sun Aug 7 20:06:18 UTC 2022


On Saturday, 6 August 2022 at 15:37:32 UTC, pascal111 wrote:
> On Friday, 5 August 2022 at 04:05:08 UTC, Salih Dincer wrote:
>> On Thursday, 4 August 2022 at 22:54:42 UTC, pascal111 wrote:
>>>
>>> I didn't notice that all what we needs to pop a range forward 
>>> is just a slice, yes, we don't need variable here.
>>
>> Ranges and Slices are not the same thing. Slicing an array is 
>> easy. This is a language possibility. For example, you need an 
>> incrementing variable for the Fibonacci Series.
>>
>> SDB at 79
>
> What!!! so where's ranges?! I thought slices of any array are 
> ranges, and understood it like that, and also there's no data 
> type called ranges, it's like if you are talking about Ghostly 
> data type!

A range is like an iterator in any other language (Java, C++, 
python3, javascript, etc), it is how D implements (lazy) 
generators https://en.wikipedia.org/wiki/Lazy_evaluation .

Ranges/Iterators don't necessarily have to be backed by memory, 
they just have to implement the interface. In D, a `empty` bool 
function that tells you whether you are at the end of the range 
or not; a `front` function to get the current value if the range 
is not `empty`; and a void function named `popFront` to advance 
to the next value if the range is not `empty`.

Once you have implemented this interface, you can use your 
"range" object with any function that accept a range; with 
`foreach`; etc.

Example of a range that is not backed by memory is a range with 
all the integer numbers.

```D
struct Integers {
   private int z = 0;

   /* or make it a bool attribute that starts as false, and you 
set to
    * true when popFront is called while z is equal to int.min */
   public bool empty() { return false; }

   public int front() { return this.z; }

   public void popFront()
   {
     /* if (this.z == int.min) { this.empty = false; return; } */
     this.z *= -1;
     if (this.z <= 0)
       --this.z;
   }
}

void main()
{
   import std.stdio : writeln;

   /* foreach is syntax sugar for
    *   for (auto r = Integers(); !r.empty(); r.popFront()) {
    *     auto z = r.front(); /+ or  const z = r.front();  or ... 
+/
    *     ...
    *   }
    * that is why it only works with ranges.
    */
   foreach (const z; Integers()) {
     writeln(z);
     if (z == 5)
       break;
   }
}
```

output:
```
0
-1
1
-2
2
-3
3
-4
4
-5
5
```

This will iterate all the integers, and the integers are of 
course, not
all in memory, and don't remain in memory after they are used, 
since
that would require infinite memory. (in the case of a range of 
integers,
not infinite, because they are constrained by being int.sizeof 
bytes,
but you could use a bignum implemenation that is not constrained 
by
that and they would actually be infinite.)

---

The equivalent in Java is the Iterable/Iterator interface.

```java
import java.util.Iterator;

public class Integers
   implements Iterable<Integer>
{
   public class IntegersIterator
     implements Iterator<Integer>
   {
     private int z = 0;
     private boolean first = true;

     public IntegersIterator(Integer z)
     {
       this.z = z;
     }

     @Override
     public boolean hasNext() { return true; }

     @Override
     public Integer next()
     {
       if (this.first) {
         this.first = false;
         return this.z;
       }

       this.z *= -1;
       if (this.z <= 0)
         --this.z;
       return this.z;
     }
   }

   @Override
   public IntegersIterator iterator() { return new 
IntegersIterator(0); }

   public static void main(String[] args)
   {
     /* syntax sugar for
      *   {
      *     final var it = newIntegers.iterator();
      *     while (it.hasNext()) {
      *       final int z = it.next();
      *       ...
      *     }
      *   }
      */
     for (final int z : new Integers()) {
       System.out.println(z);
       if (z == 5)
         break;
     }
   }
}
```

The equivalent in python is a generator function:
```python
def integers():
   z = 0
   yield z
   while True:
     z *= -1
     if z <= 0:
       z -= 1
     yield z

for z in integers():
   print(z)
   if z == 5:
     break
```

etc



More information about the Digitalmars-d-learn mailing list