On 1/19/22 21:24, Salih Dincer wrote:

> ```d
>    size_t length() inout {
>      //return last_ - first_ + 1 - empty_;/*
>      auto len = 1 + last_ - first_;
>      return cast(size_t)len;//*/
>    }
> ```

Good catch but we can't ignore '- empty_'. Otherwise an empty range will return 1.

> But it only works on integers.

After fixing the size_t issue, it should work on user-defined types as well. In fact, it is better to leave the return type as auto so that it works with user-defined types that support the length expression but is a different type like e.g. MyDiffType.

Having said that, floating point types don't make sense with the semantics of a *bidirectional and inclusive* range. :) Let's see how it looks for ranges where the step size is 0.3:

import std.stdio;

void main() {
  float beg = 0.0;
  float end = 1.0;
  float step = 0.3;

  writeln("\nIncrementing:");
  for (float f = beg; f <= end; f += step) {
    report(f);
  }

  writeln("\nDecrementing:");
  for (float f = end; f >= beg; f -= step) {
    report(f);
  }
}

void report(float f) {
  writefln!"%.16f"(f);
}

Here is the output:

Incrementing:
0.0000000000000000
0.3000000119209290
0.6000000238418579
0.9000000357627869
                <-- Where is 1.0?
Decrementing:
1.0000000000000000
0.6999999880790710
0.3999999761581421
0.0999999642372131
                <-- Where is 0.0?

So if we add the 1.0 value after 0.9000000357627869 to be *inclusive*, then that last step would not be 0.3 anymore. (Thinking about it, step would mess up things for integral types as well; so, it must be checked during construction.)

The other obvious issue in the output is that a floating point iota cannot be bidirectional because the element values would be different.

Ali

Reply via email to