loop ($x = 1.0; $x <= 2.0; $x += (1/9)), it's a crapshoot whether you get the "2.0" or not, and even if you do, it might actually be 1.99998 or something like that. Usually in these cases getting the exact ending value is highly desirable (as it is an edge case).
(Before getting into potential solutions for this, let me note that this particular example is already solvable in the latest Rakudo builds using Rats.
loop ($x = 1; $x <= 2; $x += (1/9))should give the exact list 1, 10/9, 11/9, 12/9, ... 17/9, 2. But that doesn't help with the fencepost, and the general problem is very ugly to solve this way!)
My first thought was that
:bymight do the trick. Unfortunately, I don't see Perl 6 specs for how
:byactually works in this sort of case, and as far as I know, it's not actually implemented yet to test. At any rate, I'd like to suggest that
:bydoes actually handle this case, if possible (ie if an element of the range is within epsilon of the
tovalue, then the
tovalue is returned instead). And I'd like to suggest two more modifiers, something like
:size(N)to specify that the Range should return N values, with the
:byvalue calculated as appropriate, and
:sections(N)to specify that the Range should return N+1 values.
In the meantime, here's a quick implementation of what I think the Range
:sizefunction should do. I believe that it is properly set up to be lazy, while laziness is available. Note that if you use integer parameters, it will return Rats!