25

When defining a range, let's say from 1 to 3, I expect:

[1, 2, 3]

Yet most range functions I come across, e.g. lodash, will do:

_.range(1, 3)
=> [1, 2]

And their definition will say: "Creates an array of numbers ... progressing from start up to, but not including, end."

Yet why the fuck not including end? What don't I understand about the concept of a frigging range that you won't include the end?

The only thing I can come up with that's this is related to the array's-indexes-start with-0-thing and someone did not want to substract `-1` when preparing a for loop over an 10 items array with range(0,10), even though they do not want a range of 0 to 10, they want a range from 0 to 9. (And they should not use a for loop here to begin with but a foreach construct anyway.)

So the length of your array does not match the final index of your array.

Bohhoo.

Yet now we can have ranges with very weird steps, and now you always have to consider your proper maximum, leading to code like:

var start = 10;
var max = 50;
var step = 10;

_.range(start, max + step, step)
=> [10, 20, 30, 40, 50]

and during code review this would scream "bug!" in my face.

And it's not only lodash doing that, but also python and dart.

Except php. Php's range is inclusive. Good job php.

Comments
  • 3
    Kotlin can do both FeelsGoodMan
  • 2
    Generally the reason is that if you start at 0, it defines the number of elements in the list
  • 11
    One advantage of exclusive ranges is that it simplifies splitting and it keeps things consistent with slice operators,
    chain(range(a,x), range(x,y)) == range(a,y) (with inclusive ranges x would be duplicated)

    range(a,x) == range(a,y)[:x]
    range(x,y) == range(a,y)[x:]

    [x:] == everything except the first x elements, [:x] == the first x elements
  • 0
    What @ItsNotMyFault said. It's also great for paging:

    function getPageIndexes(page) {
    return range(page * PAGE_SIZE, (page + 1) * PAGE_SIZE);
    }
Add Comment