On 2/12/16 10:59 AM, Jonathan M Davis wrote:
On Friday, 12 February 2016 at 14:36:29 UTC, Meta wrote:
On Friday, 12 February 2016 at 08:11:57 UTC, Jonathan M Davis wrote:
What it comes down to is that length should always be size_t. That's
what it is for arrays, and that's what most code expects. Allowing
other types just causes trouble for generic code. However, in the
case of iota with long, if length is size_t, then on 32-bit systems,
it's possible to have a range from iota which is longer than size_t
can represent (much as it would normally be crazy to have a range
that long). So, at some point, someone made it so that iota uses
ulong for length instead of size_t when it's a range of longs or
ulongs. It's the only thing in Phobos that does, and it causes
problems. Changing it back to size_t has been discussed but not
agreed upon. But we're between a rock and a hard place with this one.
There is no clean solution.

Personally, I'd very much like to see iota just always use size_t for
length like every other range (the only ranges which would be
affected would be ludicrously long anyway, and it would only affect
32-bit programs). But that hasn't happened yet, so iota over longs
and ulongs doesn't behave nicely on 32-bit systems.

Regardless of which way we go, the problem will _eventually_ go away
when 32-bit systems finally die out, but that's likely to take a while.

- Jonathan M Davis

What about adding another overload of iota, say, iotaEx or something
along those lines. All it would do is the following:

auto iotaEx(B, E)(B begin, E end)
{
    assert(unsigned(end - begin) <= size_t.max);

    static struct Result
    {
        typeof(iota(begin, end)) payload;

        @property size_t length()
        {
            return cast(size_t)payload.length;
        }

        alias payload this;
    }

    return Result(iota(begin, end));
}

It would be far better IMHO to just do a check in iota and throw a
RangeError if the length wouldn't fit in size_t. Having length ever be
anything other than size_t is just going to cause problems with other
ranges. On 32-bit systems, you lose out on the ability to have a range
that covers all values of long or ulong, but that's of very limited
usefulness anyway, and as long as the number of elements is no greater
than size_t.max, it would be fine - which would cover virtually all use
cases. No, it's not perfect, but allowing length to be anything but
size_t just causes bugs - especially in generic code.

Just because you have a range with a ulong length doesn't mean you are going to iterate the entire thing.

What we need is this:

standardLength(R)(R r) if (isInputRange!R && hasLength!R)
{
   static if(is(typeof(r.length) == size_t)) return r;
   else
   {
      static struct Result
      {
         R wrapped;
         size_t length() { return to!size_t(wrapped.length); }
         alias wrapped this;
      }
      return Result(r);
   }
}

-Steve

Reply via email to